From 1528b10b091ae3040e1cef3298f745aa19bceda8 Mon Sep 17 00:00:00 2001 From: John Stairs Date: Fri, 21 Sep 2018 10:42:59 -0700 Subject: [PATCH] Adds support for consistency headers (#8) The service now supports x-ms-consistency-level and x-ms-session-token HTTP headers for controlling Cosmos DB consistency. There is also a configuration setting for the default consistency level to use. We're adding the HTTP request and response headers to the IFhirContext, and a DocumentClientWithConsistencyLevelFromContext class, which implements IDocumentClient, is responsible biding a database request's consistency settings with the IFhirContext's headers. Most of DocumentClientWithConsistencyLevelFromContext is generated at build time (with incremental build awareness) with a tool. This tool uses Roslyn to generate the code and can be used in the future for other coge generation needs (such as an instrumented IDocumentClient for telemetry). --- Microsoft.Health.Fhir.sln | 11 +- samples/templates/default-azuredeploy.json | 22 +- .../Context/FhirRequestContextMiddleware.cs | 12 +- .../Features/Context/FhirRequestContext.cs | 31 +- .../Features/Context/IFhirRequestContext.cs | 6 + ...entWithConsistencyLevelFromContextTests.cs | 217 +++ .../Storage/DocumentClientInitializerTests.cs | 3 +- .../Configs/CosmosDataStoreConfiguration.cs | 3 + .../Consistency/CosmosDbConsistencyHeaders.cs | 14 + ...thConsistencyLevelFromContext.Generated.cs | 1311 +++++++++++++++++ ...ntClientWithConsistencyLevelFromContext.cs | 186 +++ .../Storage/DocumentClientInitializer.cs | 11 +- .../Microsoft.Health.Fhir.CosmosDb.csproj | 21 + .../Resources.Designer.cs | 18 + .../Resources.resx | 8 +- .../appsettings.json | 1 + .../Rest/HttpIntegrationTestFixture.cs | 48 +- .../Persistence/CosmosAdminDataStore.cs | 4 +- ...egatingInterfaceImplementationGenerator.cs | 150 ++ ...ithConsistencyLevelFromContextGenerator.cs | 114 ++ .../ICodeGenerator.cs | 14 + ...h.Extensions.BuildTimeCodeGenerator.csproj | 24 + .../Program.cs | 51 + .../TypeExtensions.cs | 49 + 24 files changed, 2288 insertions(+), 41 deletions(-) create mode 100644 src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Consistency/DocumentClientWithConsistencyLevelFromContextTests.cs create mode 100644 src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/CosmosDbConsistencyHeaders.cs create mode 100644 src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.Generated.cs create mode 100644 src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.cs create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DelegatingInterfaceImplementationGenerator.cs create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DocumentClientWithConsistencyLevelFromContextGenerator.cs create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/ICodeGenerator.cs create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Program.cs create mode 100644 tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/TypeExtensions.cs diff --git a/Microsoft.Health.Fhir.sln b/Microsoft.Health.Fhir.sln index 0a2f82ce5e..3edfbbd0b3 100644 --- a/Microsoft.Health.Fhir.sln +++ b/Microsoft.Health.Fhir.sln @@ -33,6 +33,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Extensions EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Extensions.DependencyInjection.UnitTests", "src\Microsoft.Health.Extensions.DependencyInjection.UnitTests\Microsoft.Health.Extensions.DependencyInjection.UnitTests.csproj", "{614DE061-52A0-4471-A3F1-50C9C907FFDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{B70945F4-01A6-4351-955B-C4A2943B5E3B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Health.Extensions.BuildTimeCodeGenerator", "tools\Microsoft.Health.Extensions.BuildTimeCodeGenerator\Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj", "{CA276939-8071-4734-9FE4-ADC825B72116}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -91,6 +95,10 @@ Global {614DE061-52A0-4471-A3F1-50C9C907FFDB}.Debug|Any CPU.Build.0 = Debug|Any CPU {614DE061-52A0-4471-A3F1-50C9C907FFDB}.Release|Any CPU.ActiveCfg = Release|Any CPU {614DE061-52A0-4471-A3F1-50C9C907FFDB}.Release|Any CPU.Build.0 = Release|Any CPU + {CA276939-8071-4734-9FE4-ADC825B72116}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CA276939-8071-4734-9FE4-ADC825B72116}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CA276939-8071-4734-9FE4-ADC825B72116}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CA276939-8071-4734-9FE4-ADC825B72116}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -109,9 +117,10 @@ Global {C015551C-0009-49CE-8C8D-B206BED0BB42} = {8AD2A324-DAB5-4380-94A5-31F7D817C384} {E2C2B117-32CD-449F-A4A8-4C8BA874D693} = {8AD2A324-DAB5-4380-94A5-31F7D817C384} {614DE061-52A0-4471-A3F1-50C9C907FFDB} = {8AD2A324-DAB5-4380-94A5-31F7D817C384} + {CA276939-8071-4734-9FE4-ADC825B72116} = {B70945F4-01A6-4351-955B-C4A2943B5E3B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - RESX_SortFileContentOnSave = True SolutionGuid = {E370FB31-CF95-47D1-B1E1-863A77973FF8} + RESX_SortFileContentOnSave = True EndGlobalSection EndGlobal diff --git a/samples/templates/default-azuredeploy.json b/samples/templates/default-azuredeploy.json index 1264f9d0d6..d1d50fde55 100644 --- a/samples/templates/default-azuredeploy.json +++ b/samples/templates/default-azuredeploy.json @@ -67,6 +67,15 @@ "metadata": { "description": "Source code branch to deploy." } + }, + "cosmosDbAccountConsistencyPolicy": { + "type": "object", + "defaultValue": { + "defaultConsistencyLevel": "Strong" + }, + "metadata": { + "description": "An object representing the default consistency policy for the Cosmos DB account. See https://docs.microsoft.com/en-us/azure/templates/microsoft.documentdb/databaseaccounts#ConsistencyPolicy" + } } }, "variables": { @@ -154,14 +163,14 @@ "type": "sourcecontrols", "condition": "[variables('deploySourceCode')]", "dependsOn": [ - "[resourceId('Microsoft.Web/Sites', variables('serviceName'))]" + "[resourceId('Microsoft.Web/Sites', variables('serviceName'))]" ], "properties": { - "RepoUrl": "[parameters('repositoryUrl')]", - "branch": "[parameters('repositoryBranch')]", - "IsManualIntegration": true + "RepoUrl": "[parameters('repositoryUrl')]", + "branch": "[parameters('repositoryBranch')]", + "IsManualIntegration": true } - } + } ] }, { @@ -172,6 +181,7 @@ "properties": { "name": "[variables('serviceName')]", "databaseAccountOfferType": "Standard", + "consistencyPolicy": "[parameters('cosmosDbAccountConsistencyPolicy')]", "locations": [ { "locationName": "[resourceGroup().location]", @@ -237,4 +247,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/Microsoft.Health.Fhir.Api/Features/Context/FhirRequestContextMiddleware.cs b/src/Microsoft.Health.Fhir.Api/Features/Context/FhirRequestContextMiddleware.cs index dbfb5e749b..0d24219424 100644 --- a/src/Microsoft.Health.Fhir.Api/Features/Context/FhirRequestContextMiddleware.cs +++ b/src/Microsoft.Health.Fhir.Api/Features/Context/FhirRequestContextMiddleware.cs @@ -39,11 +39,13 @@ public Task Invoke(HttpContext context, IFhirRequestContextAccessor fhirRequestC request.QueryString); var fhirRequestContext = new FhirRequestContext( - request.Method, - uriInString, - baseUriInString, - ValueSets.AuditEventType.RestFulOperation, - correlationIdProvider.Invoke()); + method: request.Method, + uriString: uriInString, + baseUriString: baseUriInString, + requestType: ValueSets.AuditEventType.RestFulOperation, + correlationId: correlationIdProvider.Invoke(), + requestHeaders: context.Request.Headers, + responseHeaders: context.Response.Headers); if (context.User != null) { diff --git a/src/Microsoft.Health.Fhir.Core/Features/Context/FhirRequestContext.cs b/src/Microsoft.Health.Fhir.Core/Features/Context/FhirRequestContext.cs index e2bfd81f46..15ce22416c 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Context/FhirRequestContext.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Context/FhirRequestContext.cs @@ -4,10 +4,11 @@ // ------------------------------------------------------------------------------------------------- using System; +using System.Collections.Generic; using System.Security.Claims; -using System.Threading; using EnsureThat; using Hl7.Fhir.Model; +using Microsoft.Extensions.Primitives; namespace Microsoft.Health.Fhir.Core.Features.Context { @@ -25,38 +26,32 @@ public FhirRequestContext( string uriString, string baseUriString, Coding requestType, - string correlationId) + string correlationId, + IDictionary requestHeaders, + IDictionary responseHeaders) { EnsureArg.IsNotNullOrWhiteSpace(method, nameof(method)); EnsureArg.IsNotNullOrWhiteSpace(uriString, nameof(uriString)); EnsureArg.IsNotNullOrWhiteSpace(baseUriString, nameof(baseUriString)); EnsureArg.IsNotNull(requestType, nameof(requestType)); EnsureArg.IsNotNullOrWhiteSpace(correlationId, nameof(correlationId)); + EnsureArg.IsNotNull(responseHeaders, nameof(responseHeaders)); + EnsureArg.IsNotNull(requestHeaders, nameof(requestHeaders)); Method = method; _uriString = uriString; _baseUriString = baseUriString; RequestType = requestType; CorrelationId = correlationId; + RequestHeaders = requestHeaders; + ResponseHeaders = responseHeaders; } public string Method { get; } - public Uri BaseUri - { - get - { - return _baseUri ?? (_baseUri = new Uri(_baseUriString)); - } - } + public Uri BaseUri => _baseUri ?? (_baseUri = new Uri(_baseUriString)); - public Uri Uri - { - get - { - return _uri ?? (_uri = new Uri(_uriString)); - } - } + public Uri Uri => _uri ?? (_uri = new Uri(_uriString)); public string CorrelationId { get; } @@ -67,5 +62,9 @@ public Uri Uri public string RouteName { get; set; } public ClaimsPrincipal Principal { get; set; } + + public IDictionary RequestHeaders { get; } + + public IDictionary ResponseHeaders { get; } } } diff --git a/src/Microsoft.Health.Fhir.Core/Features/Context/IFhirRequestContext.cs b/src/Microsoft.Health.Fhir.Core/Features/Context/IFhirRequestContext.cs index 785408967e..3a1474e0f5 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Context/IFhirRequestContext.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Context/IFhirRequestContext.cs @@ -4,8 +4,10 @@ // ------------------------------------------------------------------------------------------------- using System; +using System.Collections.Generic; using System.Security.Claims; using Hl7.Fhir.Model; +using Microsoft.Extensions.Primitives; namespace Microsoft.Health.Fhir.Core.Features.Context { @@ -26,5 +28,9 @@ public interface IFhirRequestContext string RouteName { get; set; } ClaimsPrincipal Principal { get; set; } + + IDictionary RequestHeaders { get; } + + IDictionary ResponseHeaders { get; } } } diff --git a/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Consistency/DocumentClientWithConsistencyLevelFromContextTests.cs b/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Consistency/DocumentClientWithConsistencyLevelFromContextTests.cs new file mode 100644 index 0000000000..e1a749d94e --- /dev/null +++ b/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Consistency/DocumentClientWithConsistencyLevelFromContextTests.cs @@ -0,0 +1,217 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using Microsoft.Azure.Documents; +using Microsoft.Azure.Documents.Client; +using Microsoft.Extensions.Primitives; +using Microsoft.Health.Fhir.Core.Features.Context; +using Microsoft.Health.Fhir.Core.Features.Persistence; +using Microsoft.Health.Fhir.CosmosDb.Features.Consistency; +using Newtonsoft.Json; +using NSubstitute; +using NSubstitute.ReturnsExtensions; +using Xunit; +using BindingFlags = System.Reflection.BindingFlags; + +namespace Microsoft.Health.Fhir.CosmosDb.UnitTests.Features.Consistency +{ + public class DocumentClientWithConsistencyLevelFromContextTests + { + private readonly IDocumentClient _innerClient; + private readonly Dictionary _requestHeaders = new Dictionary(); + private readonly Dictionary _responseHeaders = new Dictionary(); + private readonly IDocumentClient _consistentClient; + private readonly IFhirRequestContextAccessor _fhirRequestContextAccessor; + + public DocumentClientWithConsistencyLevelFromContextTests() + { + _innerClient = Substitute.For(); + _fhirRequestContextAccessor = Substitute.For(); + _fhirRequestContextAccessor.FhirRequestContext.RequestHeaders.Returns(_requestHeaders); + _fhirRequestContextAccessor.FhirRequestContext.ResponseHeaders.Returns(_responseHeaders); + + _consistentClient = new DocumentClientWithConsistencyLevelFromContext(_innerClient, _fhirRequestContextAccessor); + } + + [Fact] + public async Task GivenACreateRequest_WithSessionConsistency_ThenTheResponseHeadersContainTheSessionToken() + { + _innerClient + .CreateDocumentAsync("coll", (1, 2), Arg.Is(o => o.ConsistencyLevel == ConsistencyLevel.Session && o.SessionToken == "1")) + .Returns(CreateResourceResponse(new Document(), HttpStatusCode.OK, new NameValueCollection { { CosmosDbConsistencyHeaders.SessionToken, "2" } })); + + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, "Session"); + _requestHeaders.Add(CosmosDbConsistencyHeaders.SessionToken, "1"); + + await _consistentClient.CreateDocumentAsync("coll", (1, 2)); + + Assert.True(_responseHeaders.TryGetValue(CosmosDbConsistencyHeaders.SessionToken, out var values)); + Assert.Equal("2", values.ToString()); + } + + [Fact] + public async Task GivenACreateRequest_WithWithNoConsistencySpecifiedAndNoRequestOptions_ThenNoRequestOptionsAreCreated() + { + _innerClient.CreateDocumentAsync("coll", (1, 2)).Returns(CreateResourceResponse(new Document(), HttpStatusCode.OK, new NameValueCollection())); + await _consistentClient.CreateDocumentAsync("coll", (1, 2)); + await _innerClient.Received().CreateDocumentAsync("coll", (1, 2)); + } + + [Fact] + public async Task GivenACreateRequest_WithNoFhirContext_ThenNoRequestOptionsAreCreated() + { + _fhirRequestContextAccessor.FhirRequestContext.ReturnsNull(); + _innerClient.CreateDocumentAsync("coll", (1, 2)).Returns(CreateResourceResponse(new Document(), HttpStatusCode.OK, new NameValueCollection())); + await _consistentClient.CreateDocumentAsync("coll", (1, 2)); + await _innerClient.Received().CreateDocumentAsync("coll", (1, 2)); + } + + [Fact] + public async Task GivenAFeedRequest_WithSessionConsistency_ThenTheResponseHeadersContainTheSessionToken() + { + _innerClient + .ReadDatabaseFeedAsync(Arg.Is(o => o.ConsistencyLevel == ConsistencyLevel.Session && o.SessionToken == "1")) + .Returns(CreateFeedResponse(Enumerable.Empty(), new NameValueCollection { { CosmosDbConsistencyHeaders.SessionToken, "2" } })); + + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, "Session"); + _requestHeaders.Add(CosmosDbConsistencyHeaders.SessionToken, "1"); + + await _consistentClient.ReadDatabaseFeedAsync(); + + Assert.True(_responseHeaders.TryGetValue(CosmosDbConsistencyHeaders.SessionToken, out var values)); + Assert.Equal("2", values.ToString()); + } + + [Fact] + public async Task GivenAFeedRequest_WithWithNoConsistencySpecifiedAndNoRequestOptions_ThenNoRequestOptionsAreCreated() + { + _innerClient.ReadDatabaseFeedAsync() + .ReturnsForAnyArgs(CreateFeedResponse(Enumerable.Empty(), new NameValueCollection())); + await _consistentClient.ReadDatabaseFeedAsync(); + await _innerClient.Received().ReadDatabaseFeedAsync(); + } + + [Fact] + public async Task GivenAFeedRequest_WithAnUnrecognizedConsistencyLevelHeaderValue_ThenABadRequestExceptionIsThrown() + { + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, "CatsAndDogs"); + + await Assert.ThrowsAsync(() => _consistentClient.ReadDatabaseFeedAsync()); + } + + [Fact] + public async Task GivenAStoredProcedureRequestWithLink_WithSessionConsistency_ThenTheResponseHeadersContainTheSessionToken() + { + _innerClient + .ExecuteStoredProcedureAsync("link", Arg.Is(o => o.ConsistencyLevel == ConsistencyLevel.Session)) + .Returns(CreateStoredProcedureResponse(42, HttpStatusCode.OK, new NameValueCollection { { CosmosDbConsistencyHeaders.SessionToken, "2" } })); + + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, "Session"); + _requestHeaders.Add(CosmosDbConsistencyHeaders.SessionToken, "1"); + + await _consistentClient.ExecuteStoredProcedureAsync("link"); + + Assert.True(_responseHeaders.TryGetValue(CosmosDbConsistencyHeaders.SessionToken, out var values)); + Assert.Equal("2", values.ToString()); + } + + [Fact] + public async Task GivenAStoredProcedureRequestWithUri_WithSessionConsistency_ThenTheResponseHeadersContainTheSessionToken() + { + _innerClient + .ExecuteStoredProcedureAsync(default(Uri), Arg.Is(o => o.ConsistencyLevel == ConsistencyLevel.Session)) + .Returns(CreateStoredProcedureResponse(42, HttpStatusCode.OK, new NameValueCollection { { CosmosDbConsistencyHeaders.SessionToken, "2" } })); + + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, "Session"); + _requestHeaders.Add(CosmosDbConsistencyHeaders.SessionToken, "1"); + + await _consistentClient.ExecuteStoredProcedureAsync(default(Uri)); + + Assert.True(_responseHeaders.TryGetValue(CosmosDbConsistencyHeaders.SessionToken, out var values)); + Assert.Equal("2", values.ToString()); + } + + [InlineData(ConsistencyLevel.Eventual, ConsistencyLevel.Strong)] + [InlineData(ConsistencyLevel.Eventual, ConsistencyLevel.BoundedStaleness)] + [InlineData(ConsistencyLevel.Session, ConsistencyLevel.Strong)] + [InlineData(ConsistencyLevel.Session, ConsistencyLevel.BoundedStaleness)] + [InlineData(ConsistencyLevel.BoundedStaleness, ConsistencyLevel.Strong)] + [Theory] + public async Task GivenAFeedRequest_WithAStrongerConsistencyLevelThanTheDefault_ThenABadRequestExceptionIsThrown(ConsistencyLevel defaultConsistencyLevel, ConsistencyLevel requestedConsistencyLevel) + { + _innerClient.ConsistencyLevel.Returns(defaultConsistencyLevel); + _requestHeaders.Add(CosmosDbConsistencyHeaders.ConsistencyLevel, requestedConsistencyLevel.ToString()); + + await Assert.ThrowsAsync(() => _consistentClient.ReadDatabaseFeedAsync()); + } + +#pragma warning disable SA1124 // Do not use regions + #region ugly reflection as a workaround for the SDK not being mock-friendly + + private static ResourceResponse CreateResourceResponse(T resource, HttpStatusCode statusCode, NameValueCollection responseHeaders) + where T : Resource, new() + { + return (ResourceResponse)CreateInstance( // internal ResourceResponse(DocumentServiceResponse response, ITypeResolver typeResolver = null) + typeof(ResourceResponse), + CreateDocumentServiceResponse(resource, statusCode, responseHeaders), + null); + } + + private static StoredProcedureResponse CreateStoredProcedureResponse(T resource, HttpStatusCode statusCode, NameValueCollection responseHeaders) + { + return (StoredProcedureResponse)CreateInstance( // internal StoredProcedureResponse(DocumentServiceResponse response, JsonSerializerSettings serializerSettings = null) + typeof(StoredProcedureResponse), + CreateDocumentServiceResponse(resource, statusCode, responseHeaders), + null); + } + + private static object CreateDocumentServiceResponse(T resource, HttpStatusCode statusCode, NameValueCollection responseHeaders) + { + var serializer = new JsonSerializer(); + var ms = new MemoryStream(); + var jsonTextWriter = new JsonTextWriter(new StreamWriter(ms)); + serializer.Serialize(jsonTextWriter, resource); + jsonTextWriter.Flush(); + ms.Position = 0; + + return CreateInstance( // internal DocumentServiceResponse(Stream body, INameValueCollection headers, HttpStatusCode statusCode, JsonSerializerSettings serializerSettings = null) + typeof(IDocumentClient).Assembly.GetType("Microsoft.Azure.Documents.DocumentServiceResponse"), + ms, + CreateInstance( // public DictionaryNameValueCollection(NameValueCollection c) + typeof(IDocumentClient).Assembly.GetType("Microsoft.Azure.Documents.Collections.DictionaryNameValueCollection"), + responseHeaders), + statusCode, + null); + } + + private static object CreateInstance(Type type, params object[] args) => Activator.CreateInstance(type, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, args, CultureInfo.InvariantCulture); + + private static FeedResponse CreateFeedResponse(IEnumerable result, NameValueCollection responseHeaders) + { + return (FeedResponse)CreateInstance( // internal FeedResponse(IEnumerable result, int count, INameValueCollection responseHeaders, bool useETagAsContinuation = false, IReadOnlyDictionary queryMetrics = null, ClientSideRequestStatistics requestStats = null, string disallowContinuationTokenMessage = null) + typeof(FeedResponse), + result, + result.Count(), + CreateInstance( // public DictionaryNameValueCollection(NameValueCollection c) + typeof(IDocumentClient).Assembly.GetType("Microsoft.Azure.Documents.Collections.DictionaryNameValueCollection"), + responseHeaders), + false, + null, + null, + null); + } + + #endregion +#pragma warning restore SA1124 // Do not use regions + } +} diff --git a/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Storage/DocumentClientInitializerTests.cs b/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Storage/DocumentClientInitializerTests.cs index 6195721997..b6797c63ab 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Storage/DocumentClientInitializerTests.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb.UnitTests/Features/Storage/DocumentClientInitializerTests.cs @@ -4,6 +4,7 @@ // ------------------------------------------------------------------------------------------------- using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Health.Fhir.Core.Features.Context; using Microsoft.Health.Fhir.CosmosDb.Configs; using Microsoft.Health.Fhir.CosmosDb.Features.Storage; using Microsoft.Health.Fhir.CosmosDb.Features.Storage.Versioning; @@ -14,7 +15,7 @@ namespace Microsoft.Health.Fhir.CosmosDb.UnitTests.Features.Storage { public class DocumentClientInitializerTests { - private readonly DocumentClientInitializer _documentClientInitializer = new DocumentClientInitializer(Substitute.For(), NullLogger.Instance, Substitute.For()); + private readonly DocumentClientInitializer _documentClientInitializer = new DocumentClientInitializer(Substitute.For(), NullLogger.Instance, Substitute.For(), Substitute.For()); private readonly CosmosDataStoreConfiguration _cosmosDataStoreConfiguration = new CosmosDataStoreConfiguration { AllowDatabaseCreation = false, diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Configs/CosmosDataStoreConfiguration.cs b/src/Microsoft.Health.Fhir.CosmosDb/Configs/CosmosDataStoreConfiguration.cs index ac1485564e..49bcc35eef 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Configs/CosmosDataStoreConfiguration.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb/Configs/CosmosDataStoreConfiguration.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; +using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; namespace Microsoft.Health.Fhir.CosmosDb.Configs @@ -23,6 +24,8 @@ public class CosmosDataStoreConfiguration public Protocol ConnectionProtocol { get; set; } = Protocol.Tcp; + public ConsistencyLevel? DefaultConsistencyLevel { get; set; } + public bool AllowDatabaseCreation { get; set; } = true; public Uri RelativeDatabaseUri => string.IsNullOrEmpty(DatabaseId) ? null : UriFactory.CreateDatabaseUri(DatabaseId); diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/CosmosDbConsistencyHeaders.cs b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/CosmosDbConsistencyHeaders.cs new file mode 100644 index 0000000000..0941238469 --- /dev/null +++ b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/CosmosDbConsistencyHeaders.cs @@ -0,0 +1,14 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +namespace Microsoft.Health.Fhir.CosmosDb.Features.Consistency +{ + internal static class CosmosDbConsistencyHeaders + { + public const string ConsistencyLevel = "x-ms-consistency-level"; + + public const string SessionToken = "x-ms-session-token"; + } +} diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.Generated.cs b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.Generated.cs new file mode 100644 index 0000000000..64263ef9b4 --- /dev/null +++ b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.Generated.cs @@ -0,0 +1,1311 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ +namespace Microsoft.Health.Fhir.CosmosDb.Features.Consistency +{ + internal partial class DocumentClientWithConsistencyLevelFromContext : Microsoft.Azure.Documents.IDocumentClient, System.IDisposable + { + private readonly Microsoft.Azure.Documents.IDocumentClient _inner; + private DocumentClientWithConsistencyLevelFromContext(Microsoft.Azure.Documents.IDocumentClient inner) + { + _inner = inner ?? throw new System.ArgumentNullException(nameof(inner)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Object Microsoft.Azure.Documents.IDocumentClient.Session + { + get + { + return _inner.Session; + } + + set + { + _inner.Session = value; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Uri Microsoft.Azure.Documents.IDocumentClient.ServiceEndpoint + { + get + { + return _inner.ServiceEndpoint; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Uri Microsoft.Azure.Documents.IDocumentClient.WriteEndpoint + { + get + { + return _inner.WriteEndpoint; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Uri Microsoft.Azure.Documents.IDocumentClient.ReadEndpoint + { + get + { + return _inner.ReadEndpoint; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + Microsoft.Azure.Documents.Client.ConnectionPolicy Microsoft.Azure.Documents.IDocumentClient.ConnectionPolicy + { + get + { + return _inner.ConnectionPolicy; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Security.SecureString Microsoft.Azure.Documents.IDocumentClient.AuthKey + { + get + { + return _inner.AuthKey; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + Microsoft.Azure.Documents.ConsistencyLevel Microsoft.Azure.Documents.IDocumentClient.ConsistencyLevel + { + get + { + return _inner.ConsistencyLevel; + } + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ExecuteStoredProcedureAsync(System.String storedProcedureLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken, params System.Object[] procedureParams) + { + return ProcessResponse(await _inner.ExecuteStoredProcedureAsync(storedProcedureLink, UpdateOptions(options), cancellationToken, procedureParams)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ExecuteStoredProcedureAsync(System.Uri storedProcedureUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken, params System.Object[] procedureParams) + { + return ProcessResponse(await _inner.ExecuteStoredProcedureAsync(storedProcedureUri, UpdateOptions(options), cancellationToken, procedureParams)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertAttachmentAsync(System.String documentLink, System.Object attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertAttachmentAsync(documentLink, attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertAttachmentAsync(System.String attachmentsLink, System.IO.Stream mediaStream, Microsoft.Azure.Documents.Client.MediaOptions options, Microsoft.Azure.Documents.Client.RequestOptions requestOptions, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertAttachmentAsync(attachmentsLink, mediaStream, options, UpdateOptions(requestOptions), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertAttachmentAsync(System.Uri documentUri, System.Object attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertAttachmentAsync(documentUri, attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertAttachmentAsync(System.Uri documentUri, System.IO.Stream mediaStream, Microsoft.Azure.Documents.Client.MediaOptions options, Microsoft.Azure.Documents.Client.RequestOptions requestOptions, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertAttachmentAsync(documentUri, mediaStream, options, UpdateOptions(requestOptions), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertDocumentAsync(System.String collectionLink, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Boolean disableAutomaticIdGeneration, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertDocumentAsync(collectionLink, document, UpdateOptions(options), disableAutomaticIdGeneration, cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertDocumentAsync(System.Uri documentCollectionUri, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Boolean disableAutomaticIdGeneration, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.UpsertDocumentAsync(documentCollectionUri, document, UpdateOptions(options), disableAutomaticIdGeneration, cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertStoredProcedureAsync(System.String collectionLink, Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertStoredProcedureAsync(collectionLink, storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertStoredProcedureAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertStoredProcedureAsync(documentCollectionUri, storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertTriggerAsync(System.String collectionLink, Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertTriggerAsync(collectionLink, trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertTriggerAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertTriggerAsync(documentCollectionUri, trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertUserDefinedFunctionAsync(System.String collectionLink, Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertUserDefinedFunctionAsync(collectionLink, function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertUserDefinedFunctionAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertUserDefinedFunctionAsync(documentCollectionUri, function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertPermissionAsync(System.String userLink, Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertPermissionAsync(userLink, permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertPermissionAsync(System.Uri userUri, Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertPermissionAsync(userUri, permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertUserAsync(System.String databaseLink, Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertUserAsync(databaseLink, user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.UpsertUserAsync(System.Uri databaseUri, Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.UpsertUserAsync(databaseUri, user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.Uri documentUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.Uri databaseUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.Uri databaseUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.Uri databaseUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + Microsoft.Azure.Documents.Linq.IDocumentQuery Microsoft.Azure.Documents.IDocumentClient.CreateDocumentChangeFeedQuery(System.Uri collectionLink, Microsoft.Azure.Documents.Client.ChangeFeedOptions feedOptions) + { + return _inner.CreateDocumentChangeFeedQuery(collectionLink, feedOptions); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(documentCollectionUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.Uri documentCollectionUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(documentCollectionUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.Uri documentCollectionUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(documentCollectionUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.Uri userUri, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(userUri, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.Uri userUri, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(userUri, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.Uri userUri, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(userUri, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentQuery(System.String documentLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateAttachmentQuery(documentLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDatabaseQuery(Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDatabaseQuery(UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDatabaseQuery(System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDatabaseQuery(sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDatabaseQuery(Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDatabaseQuery(querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.String databaseLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.String databaseLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionQuery(System.String databaseLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentCollectionQuery(databaseLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateStoredProcedureQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateTriggerQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateTriggerQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserDefinedFunctionQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateConflictQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateConflictQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateDocumentQuery(System.String collectionLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateDocumentQuery(collectionLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + Microsoft.Azure.Documents.Linq.IDocumentQuery Microsoft.Azure.Documents.IDocumentClient.CreateDocumentChangeFeedQuery(System.String collectionLink, Microsoft.Azure.Documents.Client.ChangeFeedOptions feedOptions) + { + return _inner.CreateDocumentChangeFeedQuery(collectionLink, feedOptions); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.String usersLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(usersLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.String usersLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(usersLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateUserQuery(System.String usersLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateUserQuery(usersLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.String permissionsLink, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(permissionsLink, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.String permissionsLink, System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(permissionsLink, sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreatePermissionQuery(System.String permissionsLink, Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreatePermissionQuery(permissionsLink, querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IOrderedQueryable Microsoft.Azure.Documents.IDocumentClient.CreateOfferQuery(Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateOfferQuery(UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateOfferQuery(System.String sqlExpression, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateOfferQuery(sqlExpression, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Linq.IQueryable Microsoft.Azure.Documents.IDocumentClient.CreateOfferQuery(Microsoft.Azure.Documents.SqlQuerySpec querySpec, Microsoft.Azure.Documents.Client.FeedOptions feedOptions) + { + return _inner.CreateOfferQuery(querySpec, UpdateOptions(feedOptions)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Threading.Tasks.Task Microsoft.Azure.Documents.IDocumentClient.GetDatabaseAccountAsync() + { + return _inner.GetDatabaseAccountAsync(); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentAsync(System.String documentLink, System.Object attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateAttachmentAsync(documentLink, attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentAsync(System.String attachmentsLink, System.IO.Stream mediaStream, Microsoft.Azure.Documents.Client.MediaOptions options, Microsoft.Azure.Documents.Client.RequestOptions requestOptions, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateAttachmentAsync(attachmentsLink, mediaStream, options, UpdateOptions(requestOptions), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentAsync(System.Uri documentUri, System.Object attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateAttachmentAsync(documentUri, attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateAttachmentAsync(System.Uri documentUri, System.IO.Stream mediaStream, Microsoft.Azure.Documents.Client.MediaOptions options, Microsoft.Azure.Documents.Client.RequestOptions requestOptions, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateAttachmentAsync(documentUri, mediaStream, options, UpdateOptions(requestOptions), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDatabaseAsync(Microsoft.Azure.Documents.Database database, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDatabaseAsync(database, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDatabaseIfNotExistsAsync(Microsoft.Azure.Documents.Database database, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDatabaseIfNotExistsAsync(database, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionAsync(System.String databaseLink, Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDocumentCollectionAsync(databaseLink, documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionIfNotExistsAsync(System.String databaseLink, Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDocumentCollectionIfNotExistsAsync(databaseLink, documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionAsync(System.Uri databaseUri, Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDocumentCollectionAsync(databaseUri, documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentCollectionIfNotExistsAsync(System.Uri databaseUri, Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateDocumentCollectionIfNotExistsAsync(databaseUri, documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentAsync(System.String collectionLink, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Boolean disableAutomaticIdGeneration, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateDocumentAsync(collectionLink, document, UpdateOptions(options), disableAutomaticIdGeneration, cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateDocumentAsync(System.Uri documentCollectionUri, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Boolean disableAutomaticIdGeneration, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.CreateDocumentAsync(documentCollectionUri, document, UpdateOptions(options), disableAutomaticIdGeneration, cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureAsync(System.String collectionLink, Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateStoredProcedureAsync(collectionLink, storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateStoredProcedureAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateStoredProcedureAsync(documentCollectionUri, storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateTriggerAsync(System.String collectionLink, Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateTriggerAsync(collectionLink, trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateTriggerAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateTriggerAsync(documentCollectionUri, trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionAsync(System.String collectionLink, Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateUserDefinedFunctionAsync(collectionLink, function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateUserDefinedFunctionAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateUserDefinedFunctionAsync(documentCollectionUri, function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateUserAsync(System.String databaseLink, Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateUserAsync(databaseLink, user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreateUserAsync(System.Uri databaseUri, Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreateUserAsync(databaseUri, user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreatePermissionAsync(System.String userLink, Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreatePermissionAsync(userLink, permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.CreatePermissionAsync(System.Uri userUri, Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.CreatePermissionAsync(userUri, permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteAttachmentAsync(System.String attachmentLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.DeleteAttachmentAsync(attachmentLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteAttachmentAsync(System.Uri attachmentUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.DeleteAttachmentAsync(attachmentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDatabaseAsync(System.String databaseLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteDatabaseAsync(databaseLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDatabaseAsync(System.Uri databaseUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteDatabaseAsync(databaseUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDocumentCollectionAsync(System.String documentCollectionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteDocumentCollectionAsync(documentCollectionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDocumentCollectionAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteDocumentCollectionAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDocumentAsync(System.String documentLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.DeleteDocumentAsync(documentLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteDocumentAsync(System.Uri documentUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.DeleteDocumentAsync(documentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteStoredProcedureAsync(System.String storedProcedureLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteStoredProcedureAsync(storedProcedureLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteStoredProcedureAsync(System.Uri storedProcedureUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteStoredProcedureAsync(storedProcedureUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteTriggerAsync(System.String triggerLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteTriggerAsync(triggerLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteTriggerAsync(System.Uri triggerUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteTriggerAsync(triggerUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteUserDefinedFunctionAsync(System.String functionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteUserDefinedFunctionAsync(functionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteUserDefinedFunctionAsync(System.Uri functionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteUserDefinedFunctionAsync(functionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteUserAsync(System.String userLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteUserAsync(userLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteUserAsync(System.Uri userUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteUserAsync(userUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeletePermissionAsync(System.String permissionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeletePermissionAsync(permissionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeletePermissionAsync(System.Uri permissionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeletePermissionAsync(permissionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteConflictAsync(System.String conflictLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteConflictAsync(conflictLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.DeleteConflictAsync(System.Uri conflictUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.DeleteConflictAsync(conflictUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceAttachmentAsync(Microsoft.Azure.Documents.Attachment attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReplaceAttachmentAsync(attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceAttachmentAsync(System.Uri attachmentUri, Microsoft.Azure.Documents.Attachment attachment, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReplaceAttachmentAsync(attachmentUri, attachment, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceDocumentCollectionAsync(Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceDocumentCollectionAsync(documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceDocumentCollectionAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.DocumentCollection documentCollection, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceDocumentCollectionAsync(documentCollectionUri, documentCollection, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceDocumentAsync(System.String documentLink, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReplaceDocumentAsync(documentLink, document, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceDocumentAsync(System.Uri documentUri, System.Object document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReplaceDocumentAsync(documentUri, document, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceDocumentAsync(Microsoft.Azure.Documents.Document document, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReplaceDocumentAsync(document, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceStoredProcedureAsync(Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceStoredProcedureAsync(storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceStoredProcedureAsync(System.Uri storedProcedureUri, Microsoft.Azure.Documents.StoredProcedure storedProcedure, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceStoredProcedureAsync(storedProcedureUri, storedProcedure, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceTriggerAsync(Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceTriggerAsync(trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceTriggerAsync(System.Uri triggerUri, Microsoft.Azure.Documents.Trigger trigger, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceTriggerAsync(triggerUri, trigger, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceUserDefinedFunctionAsync(Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceUserDefinedFunctionAsync(function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceUserDefinedFunctionAsync(System.Uri userDefinedFunctionUri, Microsoft.Azure.Documents.UserDefinedFunction function, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceUserDefinedFunctionAsync(userDefinedFunctionUri, function, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplacePermissionAsync(Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplacePermissionAsync(permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplacePermissionAsync(System.Uri permissionUri, Microsoft.Azure.Documents.Permission permission, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplacePermissionAsync(permissionUri, permission, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceUserAsync(Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceUserAsync(user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceUserAsync(System.Uri userUri, Microsoft.Azure.Documents.User user, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReplaceUserAsync(userUri, user, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReplaceOfferAsync(Microsoft.Azure.Documents.Offer offer) + { + return ProcessResponse(await _inner.ReplaceOfferAsync(offer)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Threading.Tasks.Task Microsoft.Azure.Documents.IDocumentClient.UpdateMediaAsync(System.String mediaLink, System.IO.Stream mediaStream, Microsoft.Azure.Documents.Client.MediaOptions options, System.Threading.CancellationToken cancellationToken) + { + return _inner.UpdateMediaAsync(mediaLink, mediaStream, options, cancellationToken); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadAttachmentAsync(System.String attachmentLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadAttachmentAsync(attachmentLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadAttachmentAsync(System.Uri attachmentUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadAttachmentAsync(attachmentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDatabaseAsync(System.String databaseLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadDatabaseAsync(databaseLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDatabaseAsync(System.Uri databaseUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadDatabaseAsync(databaseUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentCollectionAsync(System.String documentCollectionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadDocumentCollectionAsync(documentCollectionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentCollectionAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadDocumentCollectionAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentAsync(System.String documentLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentAsync(documentLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentAsync(System.Uri documentUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentAsync(documentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentAsync(System.String documentLink, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentAsync(documentLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentAsync(System.Uri documentUri, Microsoft.Azure.Documents.Client.RequestOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentAsync(documentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadStoredProcedureAsync(System.String storedProcedureLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadStoredProcedureAsync(storedProcedureLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadStoredProcedureAsync(System.Uri storedProcedureUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadStoredProcedureAsync(storedProcedureUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadTriggerAsync(System.String triggerLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadTriggerAsync(triggerLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadTriggerAsync(System.Uri triggerUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadTriggerAsync(triggerUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserDefinedFunctionAsync(System.String functionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadUserDefinedFunctionAsync(functionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserDefinedFunctionAsync(System.Uri functionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadUserDefinedFunctionAsync(functionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPermissionAsync(System.String permissionLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadPermissionAsync(permissionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPermissionAsync(System.Uri permissionUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadPermissionAsync(permissionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserAsync(System.String userLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadUserAsync(userLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserAsync(System.Uri userUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadUserAsync(userUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadConflictAsync(System.String conflictLink, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadConflictAsync(conflictLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadConflictAsync(System.Uri conflictUri, Microsoft.Azure.Documents.Client.RequestOptions options) + { + return ProcessResponse(await _inner.ReadConflictAsync(conflictUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadOfferAsync(System.String offerLink) + { + return ProcessResponse(await _inner.ReadOfferAsync(offerLink)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Threading.Tasks.Task Microsoft.Azure.Documents.IDocumentClient.ReadMediaMetadataAsync(System.String mediaLink) + { + return _inner.ReadMediaMetadataAsync(mediaLink); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + System.Threading.Tasks.Task Microsoft.Azure.Documents.IDocumentClient.ReadMediaAsync(System.String mediaLink, System.Threading.CancellationToken cancellationToken) + { + return _inner.ReadMediaAsync(mediaLink, cancellationToken); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadAttachmentFeedAsync(System.String attachmentsLink, Microsoft.Azure.Documents.Client.FeedOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadAttachmentFeedAsync(attachmentsLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadAttachmentFeedAsync(System.Uri documentUri, Microsoft.Azure.Documents.Client.FeedOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadAttachmentFeedAsync(documentUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDatabaseFeedAsync(Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadDatabaseFeedAsync(UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPartitionKeyRangeFeedAsync(System.String partitionKeyRangesOrCollectionLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadPartitionKeyRangeFeedAsync(partitionKeyRangesOrCollectionLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPartitionKeyRangeFeedAsync(System.Uri partitionKeyRangesOrCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadPartitionKeyRangeFeedAsync(partitionKeyRangesOrCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentCollectionFeedAsync(System.String collectionsLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadDocumentCollectionFeedAsync(collectionsLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentCollectionFeedAsync(System.Uri databaseUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadDocumentCollectionFeedAsync(databaseUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentFeedAsync(System.String documentsLink, Microsoft.Azure.Documents.Client.FeedOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentFeedAsync(documentsLink, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadDocumentFeedAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options, System.Threading.CancellationToken cancellationToken) + { + return ProcessResponse(await _inner.ReadDocumentFeedAsync(documentCollectionUri, UpdateOptions(options), cancellationToken)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadStoredProcedureFeedAsync(System.String storedProceduresLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadStoredProcedureFeedAsync(storedProceduresLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadStoredProcedureFeedAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadStoredProcedureFeedAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadTriggerFeedAsync(System.String triggersLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadTriggerFeedAsync(triggersLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadTriggerFeedAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadTriggerFeedAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserDefinedFunctionFeedAsync(System.String userDefinedFunctionsLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadUserDefinedFunctionFeedAsync(userDefinedFunctionsLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserDefinedFunctionFeedAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadUserDefinedFunctionFeedAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPermissionFeedAsync(System.String permissionsLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadPermissionFeedAsync(permissionsLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadPermissionFeedAsync(System.Uri userUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadPermissionFeedAsync(userUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserFeedAsync(System.String usersLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadUserFeedAsync(usersLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadUserFeedAsync(System.Uri databaseUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadUserFeedAsync(databaseUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadConflictFeedAsync(System.String conflictsLink, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadConflictFeedAsync(conflictsLink, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadConflictFeedAsync(System.Uri documentCollectionUri, Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadConflictFeedAsync(documentCollectionUri, UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ReadOffersFeedAsync(Microsoft.Azure.Documents.Client.FeedOptions options) + { + return ProcessResponse(await _inner.ReadOffersFeedAsync(UpdateOptions(options))); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ExecuteStoredProcedureAsync(System.String storedProcedureLink, Microsoft.Azure.Documents.Client.RequestOptions options, params System.Object[] procedureParams) + { + return ProcessResponse(await _inner.ExecuteStoredProcedureAsync(storedProcedureLink, UpdateOptions(options), procedureParams)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + async System.Threading.Tasks.Task> Microsoft.Azure.Documents.IDocumentClient.ExecuteStoredProcedureAsync(System.Uri storedProcedureUri, Microsoft.Azure.Documents.Client.RequestOptions options, params System.Object[] procedureParams) + { + return ProcessResponse(await _inner.ExecuteStoredProcedureAsync(storedProcedureUri, UpdateOptions(options), procedureParams)); + } + + [System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute] + void System.IDisposable.Dispose() + { + ((System.IDisposable)_inner).Dispose(); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.cs b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.cs new file mode 100644 index 0000000000..65a3346131 --- /dev/null +++ b/src/Microsoft.Health.Fhir.CosmosDb/Features/Consistency/DocumentClientWithConsistencyLevelFromContext.cs @@ -0,0 +1,186 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using EnsureThat; +using Microsoft.Azure.Documents; +using Microsoft.Azure.Documents.Client; +using Microsoft.Health.Fhir.Core.Features.Context; +using Microsoft.Health.Fhir.Core.Features.Persistence; + +namespace Microsoft.Health.Fhir.CosmosDb.Features.Consistency +{ + /// + /// A wrapper that sets the consistency level and, if applicable, the session token + /// for each request. + /// + internal sealed partial class DocumentClientWithConsistencyLevelFromContext + { + private static readonly string ValidConsistencyLevelsForErrorMessage = string.Join(", ", Enum.GetNames(typeof(ConsistencyLevel)).Select(v => $"'{v}'")); + private readonly IFhirRequestContextAccessor _fhirRequestContextAccessor; + + public DocumentClientWithConsistencyLevelFromContext(IDocumentClient inner, IFhirRequestContextAccessor fhirRequestContextAccessor) + : this(inner) + { + EnsureArg.IsNotNull(fhirRequestContextAccessor, nameof(fhirRequestContextAccessor)); + _fhirRequestContextAccessor = fhirRequestContextAccessor; + } + + private RequestOptions UpdateOptions(RequestOptions options) + { + (ConsistencyLevel? consistencyLevel, string sessionToken) = GetConsistencyHeaders(); + + if (consistencyLevel == null && string.IsNullOrEmpty(sessionToken)) + { + return options; + } + + if (options == null) + { + options = new RequestOptions(); + } + + if (consistencyLevel != null) + { + options.ConsistencyLevel = consistencyLevel; + } + + if (!string.IsNullOrEmpty(sessionToken)) + { + options.SessionToken = sessionToken; + } + + return options; + } + + private FeedOptions UpdateOptions(FeedOptions options) + { + (ConsistencyLevel? consistencyLevel, string sessionToken) = GetConsistencyHeaders(); + + if (consistencyLevel == null && string.IsNullOrEmpty(sessionToken)) + { + return options; + } + + if (options == null) + { + options = new FeedOptions(); + } + + if (consistencyLevel != null) + { + options.ConsistencyLevel = consistencyLevel; + } + + if (!string.IsNullOrEmpty(sessionToken)) + { + options.SessionToken = sessionToken; + } + + return options; + } + + private (ConsistencyLevel? consistencyLevel, string sessionToken) GetConsistencyHeaders() + { + IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext; + + if (fhirRequestContext == null) + { + return (null, null); + } + + ConsistencyLevel? requestedConsistencyLevel = null; + + if (fhirRequestContext.RequestHeaders.TryGetValue(CosmosDbConsistencyHeaders.ConsistencyLevel, out var values)) + { + if (!Enum.TryParse(values, out ConsistencyLevel parsedLevel)) + { + throw new BadRequestException(string.Format(CultureInfo.CurrentCulture, Resources.UnrecognizedConsistencyLevel, values, ValidConsistencyLevelsForErrorMessage)); + } + + if (parsedLevel != _inner.ConsistencyLevel) + { + if (!ValidateConsistencyLevel(parsedLevel)) + { + throw new BadRequestException(string.Format(Resources.InvalidConsistencyLevel, parsedLevel, _inner.ConsistencyLevel)); + } + + requestedConsistencyLevel = parsedLevel; + } + } + + fhirRequestContext.RequestHeaders.TryGetValue(CosmosDbConsistencyHeaders.SessionToken, out values); + + return (requestedConsistencyLevel, values); + } + + /// + /// Determines whether the requested consistency level is valid given the DocumentClient's consistency level. + /// DocumentClient throws an ArgumentException when a requested consistency level is invalid. Since ArgumentException + /// is not very specific and we would rather not inspect the exception message, we do the check ourselves here. + /// Copied from the DocumentDB SDK. + /// + private bool ValidateConsistencyLevel(ConsistencyLevel desiredConsistency) + { + switch (_inner.ConsistencyLevel) + { + case ConsistencyLevel.Strong: + return desiredConsistency == ConsistencyLevel.Strong || desiredConsistency == ConsistencyLevel.BoundedStaleness || desiredConsistency == ConsistencyLevel.Session || desiredConsistency == ConsistencyLevel.Eventual || desiredConsistency == ConsistencyLevel.ConsistentPrefix; + case ConsistencyLevel.BoundedStaleness: + return desiredConsistency == ConsistencyLevel.BoundedStaleness || desiredConsistency == ConsistencyLevel.Session || desiredConsistency == ConsistencyLevel.Eventual || desiredConsistency == ConsistencyLevel.ConsistentPrefix; + case ConsistencyLevel.Session: + case ConsistencyLevel.Eventual: + case ConsistencyLevel.ConsistentPrefix: + return desiredConsistency == ConsistencyLevel.Session || desiredConsistency == ConsistencyLevel.Eventual || desiredConsistency == ConsistencyLevel.ConsistentPrefix; + default: + throw new NotSupportedException(nameof(_inner.ConsistencyLevel)); + } + } + + private T ProcessResponse(T response) + where T : ResourceResponseBase + { + AddSessionTokenToResponseHeaders(response.SessionToken); + return response; + } + + private FeedResponse ProcessResponse(FeedResponse response) + { + AddSessionTokenToResponseHeaders(response.SessionToken); + return response; + } + + private StoredProcedureResponse ProcessResponse(StoredProcedureResponse response) + { + AddSessionTokenToResponseHeaders(response.SessionToken); + return response; + } + + private void AddSessionTokenToResponseHeaders(string sessionToken) + { + if (!string.IsNullOrEmpty(sessionToken)) + { + IFhirRequestContext fhirRequestContext = _fhirRequestContextAccessor.FhirRequestContext; + if (fhirRequestContext != null) + { + fhirRequestContext.ResponseHeaders[CosmosDbConsistencyHeaders.SessionToken] = sessionToken; + } + } + } + + Task> IDocumentClient.ExecuteStoredProcedureAsync(string storedProcedureLink, params object[] procedureParams) + { + return ((IDocumentClient)this).ExecuteStoredProcedureAsync(storedProcedureLink, UpdateOptions(default(RequestOptions)), procedureParams); + } + + Task> IDocumentClient.ExecuteStoredProcedureAsync(Uri storedProcedureUri, params dynamic[] procedureParams) + { + return ((IDocumentClient)this).ExecuteStoredProcedureAsync(storedProcedureUri, UpdateOptions(default(RequestOptions)), procedureParams); + } + } +} diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/DocumentClientInitializer.cs b/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/DocumentClientInitializer.cs index 30f130ce73..2294875e21 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/DocumentClientInitializer.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/DocumentClientInitializer.cs @@ -10,8 +10,10 @@ using Microsoft.Azure.Documents; using Microsoft.Azure.Documents.Client; using Microsoft.Extensions.Logging; +using Microsoft.Health.Fhir.Core.Features.Context; using Microsoft.Health.Fhir.Core.Features.Persistence; using Microsoft.Health.Fhir.CosmosDb.Configs; +using Microsoft.Health.Fhir.CosmosDb.Features.Consistency; using Microsoft.Health.Fhir.CosmosDb.Features.Storage.Versioning; using Newtonsoft.Json; using Newtonsoft.Json.Converters; @@ -23,16 +25,19 @@ public class DocumentClientInitializer : IDocumentClientInitializer private readonly IDocumentClientTestProvider _testProvider; private readonly ILogger _logger; private readonly IUpgradeManager _upgradeManager; + private readonly IFhirRequestContextAccessor _fhirRequestContextAccessor; - public DocumentClientInitializer(IDocumentClientTestProvider testProvider, ILogger logger, IUpgradeManager upgradeManager) + public DocumentClientInitializer(IDocumentClientTestProvider testProvider, ILogger logger, IUpgradeManager upgradeManager, IFhirRequestContextAccessor fhirRequestContextAccessor) { EnsureArg.IsNotNull(logger, nameof(logger)); EnsureArg.IsNotNull(upgradeManager, nameof(upgradeManager)); EnsureArg.IsNotNull(testProvider, nameof(testProvider)); + EnsureArg.IsNotNull(fhirRequestContextAccessor, nameof(fhirRequestContextAccessor)); _testProvider = testProvider; _logger = logger; _upgradeManager = upgradeManager; + _fhirRequestContextAccessor = fhirRequestContextAccessor; } /// @@ -81,7 +86,9 @@ public IDocumentClient CreateDocumentClient(CosmosDataStoreConfiguration configu // if the values don't always have complete 7 digits, the comparison might not work properly. serializerSettings.Converters.Add(new IsoDateTimeConverter { DateTimeFormat = "o" }); - return new DocumentClient(new Uri(configuration.Host), configuration.Key, serializerSettings, connectionPolicy); + return new DocumentClientWithConsistencyLevelFromContext( + new DocumentClient(new Uri(configuration.Host), configuration.Key, serializerSettings, connectionPolicy, configuration.DefaultConsistencyLevel), + _fhirRequestContextAccessor); } /// diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Microsoft.Health.Fhir.CosmosDb.csproj b/src/Microsoft.Health.Fhir.CosmosDb/Microsoft.Health.Fhir.CosmosDb.csproj index 508ec4ecce..c543081c2f 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Microsoft.Health.Fhir.CosmosDb.csproj +++ b/src/Microsoft.Health.Fhir.CosmosDb/Microsoft.Health.Fhir.CosmosDb.csproj @@ -9,6 +9,7 @@ Full latest true + ..\..\tools\Microsoft.Health.Extensions.BuildTimeCodeGenerator\Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj @@ -33,6 +34,7 @@ + @@ -52,4 +54,23 @@ + + + DocumentClientWithConsistencyLevelFromContextGenerator + Microsoft.Health.Fhir.CosmosDb.Features.Consistency + + + + + + @(_ResolvedProjectReferencePaths) + + + + + + + + + diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs b/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs index b1b62cdb8d..a564e838a5 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs @@ -60,6 +60,15 @@ internal Resources() { } } + /// + /// Looks up a localized string similar to Consistency level '{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 Unhandled {0} '{1}'.. /// @@ -68,5 +77,14 @@ internal static string UnhandledEnumValue { return ResourceManager.GetString("UnhandledEnumValue", resourceCulture); } } + + /// + /// Looks up a localized string similar to Invalid consitency level '{0}'. Valid values are {1}.. + /// + internal static string UnrecognizedConsistencyLevel { + get { + return ResourceManager.GetString("UnrecognizedConsistencyLevel", resourceCulture); + } + } } } diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx b/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx index e91cfae27d..2d83bb5ecb 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx +++ b/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx @@ -117,7 +117,13 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Consistency level '{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. + Unhandled {0} '{1}'. - \ No newline at end of file + + Invalid consitency level '{0}'. Valid values are {1}. + + diff --git a/src/Microsoft.Health.Fhir.Web/appsettings.json b/src/Microsoft.Health.Fhir.Web/appsettings.json index 21b9ef3f55..3558ebb346 100644 --- a/src/Microsoft.Health.Fhir.Web/appsettings.json +++ b/src/Microsoft.Health.Fhir.Web/appsettings.json @@ -9,6 +9,7 @@ "CollectionId": "fhir", "ConnectionMode": "Direct", "ConnectionProtocol": "Tcp", + "DefaultConsistencyLevel": "Session", "PreferredLocations": [] }, "IdentityServer": { diff --git a/test/Microsoft.Health.Fhir.Tests.E2E/Rest/HttpIntegrationTestFixture.cs b/test/Microsoft.Health.Fhir.Tests.E2E/Rest/HttpIntegrationTestFixture.cs index 12f0c575ac..795dc6bd76 100644 --- a/test/Microsoft.Health.Fhir.Tests.E2E/Rest/HttpIntegrationTestFixture.cs +++ b/test/Microsoft.Health.Fhir.Tests.E2E/Rest/HttpIntegrationTestFixture.cs @@ -6,17 +6,16 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net.Http; using System.Reflection; +using System.Threading; +using System.Threading.Tasks; using Hl7.Fhir.Rest; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.ApplicationParts; -using Microsoft.AspNetCore.Mvc.Controllers; -using Microsoft.AspNetCore.Mvc.ViewComponents; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using FhirClient = Microsoft.Health.Fhir.Tests.E2E.Common.FhirClient; @@ -44,22 +43,23 @@ protected HttpIntegrationTestFixture(string targetProjectParentDirectory) _environmentUrl = Environment.GetEnvironmentVariable("TestEnvironmentUrl"); + HttpMessageHandler messageHandler; + if (string.IsNullOrWhiteSpace(_environmentUrl)) { _environmentUrl = "http://localhost/"; StartInMemoryServer(targetProjectParentDirectory); - HttpClient = _server.CreateClient(); - + messageHandler = _server.CreateHandler(); IsUsingInProcTestServer = true; } else { - HttpClient = new HttpClient(); + messageHandler = new HttpClientHandler(); } - HttpClient.BaseAddress = new Uri(_environmentUrl); + HttpClient = new HttpClient(new SessionMessageHandler(messageHandler)) { BaseAddress = new Uri(_environmentUrl) }; FhirClient = new FhirClient(HttpClient, ResourceFormat.Json); FhirXmlClient = new Lazy(() => new FhirClient(HttpClient, ResourceFormat.Xml)); @@ -168,5 +168,37 @@ private static string GetProjectPath(string projectRelativePath, Type startupTyp throw new Exception($"Project root could not be located for startup type {startupType.FullName}"); } + + /// + /// An that maintains session consistency between requests. + /// + private class SessionMessageHandler : DelegatingHandler + { + private string _sessionToken; + + public SessionMessageHandler(HttpMessageHandler innerHandler) + : base(innerHandler) + { + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + if (!string.IsNullOrEmpty(_sessionToken)) + { + request.Headers.TryAddWithoutValidation("x-ms-session-token", _sessionToken); + } + + request.Headers.TryAddWithoutValidation("x-ms-consistency-level", "Session"); + + var response = await base.SendAsync(request, cancellationToken); + + if (response.Headers.TryGetValues("x-ms-session-token", out var tokens)) + { + _sessionToken = tokens.SingleOrDefault(); + } + + return response; + } + } } } diff --git a/test/Microsoft.Health.Fhir.Tests.Integration/Persistence/CosmosAdminDataStore.cs b/test/Microsoft.Health.Fhir.Tests.Integration/Persistence/CosmosAdminDataStore.cs index 268bef2003..fefaa7c12a 100644 --- a/test/Microsoft.Health.Fhir.Tests.Integration/Persistence/CosmosAdminDataStore.cs +++ b/test/Microsoft.Health.Fhir.Tests.Integration/Persistence/CosmosAdminDataStore.cs @@ -8,12 +8,14 @@ using System.Threading.Tasks; using Microsoft.Azure.Documents; using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Health.Fhir.Core.Features.Context; using Microsoft.Health.Fhir.Core.Features.Persistence; using Microsoft.Health.Fhir.CosmosDb.Configs; using Microsoft.Health.Fhir.CosmosDb.Features.Storage; using Microsoft.Health.Fhir.CosmosDb.Features.Storage.Continuation; using Microsoft.Health.Fhir.CosmosDb.Features.Storage.StoredProcedures; using Microsoft.Health.Fhir.CosmosDb.Features.Storage.Versioning; +using NSubstitute; namespace Microsoft.Health.Fhir.Tests.Integration.Persistence { @@ -46,7 +48,7 @@ public CosmosAdminDataStore() var upgradeManager = new CollectionUpgradeManager(updaters, _cosmosDataStoreConfiguration, dbLock, NullLogger.Instance); IDocumentClientTestProvider testProvider = new DocumentClientReadWriteTestProvider(); - var documentClientInitializer = new DocumentClientInitializer(testProvider, NullLogger.Instance, upgradeManager); + var documentClientInitializer = new DocumentClientInitializer(testProvider, NullLogger.Instance, upgradeManager, Substitute.For()); _documentClient = documentClientInitializer.CreateDocumentClient(_cosmosDataStoreConfiguration); documentClientInitializer.InitializeDataStore(_documentClient, _cosmosDataStoreConfiguration).GetAwaiter().GetResult(); diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DelegatingInterfaceImplementationGenerator.cs b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DelegatingInterfaceImplementationGenerator.cs new file mode 100644 index 0000000000..162e4f92bb --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DelegatingInterfaceImplementationGenerator.cs @@ -0,0 +1,150 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator +{ + /// + /// Generates a class that implements one or more interfaces, delegating implementation to an inner field. + /// Implementations are explicit. + /// + internal class DelegatingInterfaceImplementationGenerator : ICodeGenerator + { + private readonly SyntaxTokenList _typeModifiers; + private readonly SyntaxTokenList _constructorModifiers; + private readonly Type[] _interfacesToImplement; + private static readonly IdentifierNameSyntax FieldName = IdentifierName("_inner"); + private static readonly AttributeListSyntax ExcludeFromCodeCoverageAttributeSyntax = AttributeList(SingletonSeparatedList(Attribute(IdentifierName(typeof(ExcludeFromCodeCoverageAttribute).FullName)))); + + public DelegatingInterfaceImplementationGenerator(SyntaxTokenList typeModifiers, SyntaxTokenList constructorModifiers, params Type[] interfacesToImplement) + { + _typeModifiers = typeModifiers; + _constructorModifiers = constructorModifiers; + _interfacesToImplement = interfacesToImplement; + } + + public SyntaxNode Generate(string namespaceName, string typeName, Compilation compilation) + { + return CompilationUnit() + .AddMembers( + NamespaceDeclaration(IdentifierName(namespaceName)) + .AddMembers(GetClass(typeName))); + } + + public ClassDeclarationSyntax GetClass(string typeName) + { + return ClassDeclaration(typeName) + .WithModifiers(_typeModifiers) + .WithBaseList(BaseList(SeparatedList(_interfacesToImplement.Select(t => (BaseTypeSyntax)SimpleBaseType(t.ToTypeSyntax()))))) + .AddMembers( + FieldDeclaration(VariableDeclaration(_interfacesToImplement[0].ToTypeSyntax()).AddVariables(VariableDeclarator(FieldName.Identifier))).AddModifiers(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.ReadOnlyKeyword)), + GetConstructor(typeName)) + .AddMembers(GetPropertiesAndMethods().ToArray()); + } + + private ConstructorDeclarationSyntax GetConstructor(string className) + { + return ConstructorDeclaration(className) + .WithModifiers(_constructorModifiers) + .AddParameterListParameters(Parameter(Identifier("inner")).WithType(_interfacesToImplement[0].ToTypeSyntax())) + .AddBodyStatements( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + FieldName, + BinaryExpression( + SyntaxKind.CoalesceExpression, + IdentifierName("inner"), + ThrowExpression( + ObjectCreationExpression(typeof(ArgumentNullException).ToTypeSyntax()) + .AddArgumentListArguments(Argument( + InvocationExpression( + IdentifierName("nameof")) + .AddArgumentListArguments(Argument( + IdentifierName("inner")))))))))); + } + + private IEnumerable GetPropertiesAndMethods() + { + for (var interfaceIndex = 0; interfaceIndex < _interfacesToImplement.Length; interfaceIndex++) + { + var interfaceType = _interfacesToImplement[interfaceIndex]; + + var typedFieldName = interfaceIndex == 0 ? (ExpressionSyntax)FieldName : ParenthesizedExpression(CastExpression(interfaceType.ToTypeSyntax(), FieldName)); + var explicitInterfaceSpecifier = ExplicitInterfaceSpecifier((NameSyntax)interfaceType.ToTypeSyntax()); + + foreach (var propertyInfo in interfaceType.GetProperties()) + { + var propertyDeclarationSyntax = PropertyDeclaration(propertyInfo.PropertyType.ToTypeSyntax(), propertyInfo.Name) + .WithExplicitInterfaceSpecifier(explicitInterfaceSpecifier) + .AddAttributeLists(ExcludeFromCodeCoverageAttributeSyntax); + + if (propertyInfo.GetGetMethod() != null) + { + propertyDeclarationSyntax = propertyDeclarationSyntax.AddAccessorListAccessors( + AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, Block(ReturnStatement(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, FieldName, IdentifierName(propertyInfo.Name)))))); + } + + if (propertyInfo.GetSetMethod() != null) + { + propertyDeclarationSyntax = propertyDeclarationSyntax.AddAccessorListAccessors( + AccessorDeclaration( + SyntaxKind.SetAccessorDeclaration, + Block(ExpressionStatement(AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, typedFieldName, IdentifierName(propertyInfo.Name)), + IdentifierName("value")))))); + } + + yield return propertyDeclarationSyntax; + } + + foreach (var methodInfo in interfaceType.GetMethods().Except(interfaceType.GetProperties().SelectMany(p => p.GetAccessors()))) + { + var method = MethodDeclaration(methodInfo.ReturnType.ToTypeSyntax(), methodInfo.Name) + .WithExplicitInterfaceSpecifier(explicitInterfaceSpecifier) + .AddParameterListParameters( + methodInfo.GetParameters().Select(p => + Parameter(Identifier(p.Name)) + .WithType(p.ParameterType.ToTypeSyntax()) + .WithModifiers(p.IsDefined(typeof(ParamArrayAttribute), false) ? TokenList(Token(SyntaxKind.ParamsKeyword)) : TokenList())) + .ToArray()) + .AddAttributeLists(ExcludeFromCodeCoverageAttributeSyntax) + .WithBody(Block()); + + if (methodInfo.IsGenericMethod) + { + method = method.WithTypeParameterList(TypeParameterList(SeparatedList(methodInfo.GetGenericArguments().Select(t => TypeParameter(t.Name))))); + } + + var methodName = methodInfo.IsGenericMethod + ? GenericName(methodInfo.Name).AddTypeArgumentListArguments(methodInfo.GetGenericArguments().Select(TypeExtensions.ToTypeSyntax).ToArray()) + : (SimpleNameSyntax)IdentifierName(methodInfo.Name); + + var invocation = InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + typedFieldName, + methodName), + ArgumentList(SeparatedList(methodInfo.GetParameters().Select(p => Argument(IdentifierName(p.Name)))))); + + var block = Block(methodInfo.ReturnType == typeof(void) ? ExpressionStatement(invocation) : (StatementSyntax)ReturnStatement(invocation)); + + method = method.WithBody(block); + + yield return method; + } + } + } + } +} diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DocumentClientWithConsistencyLevelFromContextGenerator.cs b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DocumentClientWithConsistencyLevelFromContextGenerator.cs new file mode 100644 index 0000000000..ab10364e70 --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/DocumentClientWithConsistencyLevelFromContextGenerator.cs @@ -0,0 +1,114 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Azure.Documents.Client; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; +using IDocumentClient = Microsoft.Azure.Documents.IDocumentClient; + +namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator +{ + /// + /// Generates a partial class for wrapping IDocumentClient, where for each call, where applicable, + /// we set ConsistencyLevel and/or SessionToken on or + /// parameters based on HTTP request headers, and we set the session consistency output header based on the response. + /// + internal class DocumentClientWithConsistencyLevelFromContextGenerator : ICodeGenerator + { + public SyntaxNode Generate(string namespaceName, string typeName, Compilation compilation) + { + // First generate a basic class that implements the interfaces and delegates to an inner field. + var generator = new DelegatingInterfaceImplementationGenerator( + typeModifiers: TokenList(Token(SyntaxKind.InternalKeyword), Token(SyntaxKind.PartialKeyword)), + constructorModifiers: TokenList(Token(SyntaxKind.PrivateKeyword)), + typeof(IDocumentClient), + typeof(IDisposable)); + + var syntaxNode = generator.Generate(namespaceName, typeName, compilation); + + compilation = compilation.AddSyntaxTrees(syntaxNode.SyntaxTree); + + // then rewrite it with logic specific to this generator + + var rewriter = new ConsistencyLevelRewriter(compilation, compilation.GetSemanticModel(syntaxNode.SyntaxTree)); + return rewriter.Visit(syntaxNode); + } + + private class ConsistencyLevelRewriter : CSharpSyntaxRewriter + { + private readonly SemanticModel _semanticModel; + private readonly INamedTypeSymbol _taskTypeSymbol; + private readonly INamedTypeSymbol[] _optionTypeSymbols; + private readonly INamedTypeSymbol[] _responseTypeSymbols; + private readonly HashSet _methodsWithOptionOverloads; + + public ConsistencyLevelRewriter(Compilation compilation, SemanticModel semanticModel) + { + // look for methods that rely on overloading instead of FeedOptions/RequestOptions being an optional parameter + + var optionParameterTypes = new[] { typeof(FeedOptions), typeof(RequestOptions) }; + _methodsWithOptionOverloads = typeof(IDocumentClient).GetMethods() + .GroupBy(m => m.Name) + .Where(g => + g.Select(m => m.GetParameters().Any(p => optionParameterTypes.Contains(p.ParameterType))).Distinct().Count() > 1) + .Select(g => g.Key).ToHashSet(); + + _taskTypeSymbol = compilation.GetTypeByMetadataName(typeof(Task<>).FullName); + _optionTypeSymbols = optionParameterTypes.Select(t => compilation.GetTypeByMetadataName(t.FullName)).ToArray(); + _responseTypeSymbols = new[] { typeof(DocumentResponse<>), typeof(FeedResponse<>), typeof(ResourceResponse<>), typeof(StoredProcedureResponse<>) }.Select(t => compilation.GetTypeByMetadataName(t.FullName)).ToArray(); + _semanticModel = semanticModel; + } + + public override SyntaxNode VisitArgument(ArgumentSyntax node) + { + ITypeSymbol type = _semanticModel.GetTypeInfo(node.Expression).Type; + + if (_optionTypeSymbols.Contains(type)) + { + return node.WithExpression(InvocationExpression(IdentifierName("UpdateOptions")).AddArgumentListArguments(node)); + } + + return base.VisitArgument(node); + } + + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + var visitedNode = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); + + if (ReferenceEquals(visitedNode, node) && + _methodsWithOptionOverloads.Contains(node.Identifier.ValueText)) + { + // Don't generate methods where the body would call an overload. + // The logic is a bit more complicated and there are only + // two methods anyway. They can be written out by hand in the + // partial class. + + return IncompleteMember(); + } + + if (_semanticModel.GetTypeInfo(node.ReturnType).Type is INamedTypeSymbol type && + type.ConstructedFrom.Equals(_taskTypeSymbol) && + type.TypeArguments[0] is INamedTypeSymbol argumentType && + argumentType.IsGenericType && + _responseTypeSymbols.Contains(argumentType.ConstructedFrom)) + { + visitedNode = visitedNode.AddModifiers(Token(SyntaxKind.AsyncKeyword)); + var invocation = visitedNode.DescendantNodes().OfType().First(); + visitedNode = visitedNode.ReplaceNode(invocation, InvocationExpression(IdentifierName("ProcessResponse")).AddArgumentListArguments(Argument(AwaitExpression(invocation)))); + + return visitedNode; + } + + return visitedNode; + } + } + } +} diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/ICodeGenerator.cs b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/ICodeGenerator.cs new file mode 100644 index 0000000000..4853f13527 --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/ICodeGenerator.cs @@ -0,0 +1,14 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator +{ + public interface ICodeGenerator + { + SyntaxNode Generate(string namespaceName, string typeName, Compilation compilation); + } +} diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj new file mode 100644 index 0000000000..e63efa22b8 --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Microsoft.Health.Extensions.BuildTimeCodeGenerator.csproj @@ -0,0 +1,24 @@ + + + + Exe + netcoreapp2.1 + ..\..\CustomAnalysisRules.ruleset + true + + latest + true + + + + + + + + + + + + + + diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Program.cs b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Program.cs new file mode 100644 index 0000000000..cf888c4ff8 --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/Program.cs @@ -0,0 +1,51 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator +{ + internal class Program + { + public static void Main(string[] args) + { + if (args.Length != 4) + { + Console.WriteLine($"Usage: dotnet {typeof(Program).Assembly.GetName().Name}.dll "); + Environment.Exit(1); + } + + string generatorName = args[0]; + string outputFile = args[1]; + string namespaceName = args[2]; + string className = Path.GetFileName(outputFile).Split('.')[0]; + string references = args[3]; + + Compilation compilation = CSharpCompilation.Create("Generated") + .AddReferences(references.Split(';').Where(File.Exists).Select(p => MetadataReference.CreateFromFile(p))); + + var generator = (ICodeGenerator)Activator.CreateInstance(Assembly.GetExecutingAssembly().GetTypes().SingleOrDefault(t => t.Name == generatorName) ?? throw new ArgumentException($"Generator '{generatorName} not found")); + + SyntaxNode syntaxNode = generator.Generate(namespaceName, className, compilation); + + syntaxNode = syntaxNode.WithLeadingTrivia( + SyntaxFactory.Comment("//------------------------------------------------------------------------------"), + SyntaxFactory.Comment("// "), + SyntaxFactory.Comment("// This code was generated by a tool."), + SyntaxFactory.Comment("//"), + SyntaxFactory.Comment("// Changes to this file may cause incorrect behavior and will be lost if"), + SyntaxFactory.Comment("// the code is regenerated."), + SyntaxFactory.Comment("// "), + SyntaxFactory.Comment("//------------------------------------------------------------------------------")); + + File.WriteAllText(outputFile, syntaxNode.NormalizeWhitespace().SyntaxTree.ToString()); + } + } +} diff --git a/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/TypeExtensions.cs b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/TypeExtensions.cs new file mode 100644 index 0000000000..bdb9528418 --- /dev/null +++ b/tools/Microsoft.Health.Extensions.BuildTimeCodeGenerator/TypeExtensions.cs @@ -0,0 +1,49 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Health.Extensions.BuildTimeCodeGenerator +{ + internal static class TypeExtensions + { + public static TypeSyntax ToTypeSyntax(this Type t) + { + if (t == typeof(void)) + { + return SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.VoidKeyword)); + } + + if (t.IsGenericParameter) + { + return SyntaxFactory.IdentifierName(t.Name); + } + + if (t.IsArray) + { + return SyntaxFactory.ArrayType( + t.GetElementType().ToTypeSyntax(), + SyntaxFactory.SingletonList( + SyntaxFactory.ArrayRankSpecifier( + SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.OmittedArraySizeExpression())))); + } + + TypeSyntax qualification = t.IsNested + ? t.DeclaringType.ToTypeSyntax() + : t.Namespace.Split('.').Select(s => (NameSyntax)SyntaxFactory.IdentifierName(s)).Aggregate((acc, next) => SyntaxFactory.QualifiedName(acc, (SimpleNameSyntax)next)); + + SimpleNameSyntax name = t.IsGenericType + ? SyntaxFactory.GenericName(t.Name.Substring(0, t.Name.IndexOf('`', StringComparison.Ordinal))) + .WithTypeArgumentList(SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(t.GetGenericArguments().Select(ToTypeSyntax)))) + : (SimpleNameSyntax)SyntaxFactory.IdentifierName(t.Name); + + return SyntaxFactory.QualifiedName((NameSyntax)qualification, name); + } + } +}