From 25c122c493604a150b4525d87aac413a74764913 Mon Sep 17 00:00:00 2001 From: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> Date: Thu, 30 Nov 2023 22:33:41 -0800 Subject: [PATCH] [Internal] Msdata/Direct: Refactors msdata/direct branch with latest v3 master and `Cosmos.Direct` Release version `3.32.0` (#4200) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Internal] Client Telemetry: Fixes tests leaking environment variables (#3517) * Adding log lines * More logs * Debugging further * Removing other builds * And more debugging * Wrong build parameters * Wrong category * Removing noise * Fixing test * Adding utils * Adding test with client telemetry enabled * Fixing leak in Client Telemetry Tests * Reenabling test * cpu monitor initialization * Adding name details * Undo another file * Updated change log and bumped up the version. (#3526) * Query: Fixes performance regression on target partition on some ORDER BY queries with continuation (#3525) * Revert performance regression caused by https://github.com/Azure/azure-cosmos-dotnet-v3/pull/1289/ * Remove irrelevant comment * Add a test for validating formatted filters for the target partition * [Internal] AI Integration: Adds SubStatusCode Information in attributes (#3533) * wip * regenerated baseline * add test * fix test Co-authored-by: Sourabh Jain * Diagnostics: Removes unused properties and reduces size (#3519) * Remove starttime and id from diagnostics string * Remove starttime and id from diagnostics string * Update xml files for trace baseline tests * Update xml files for trace baseline tests * Update xml files for trace baseline tests * Whitespaces update * Changed starttime position based on code review Co-authored-by: Matias Quaranta * [Internal] docs: Add address caches conceptual flow (#3534) * Rough draft * Some more changes * Adding a new section * Some more refinement * Some changes Lets get the feedback * Some MISC changes * Release: Adds SDK version and changelog for 3.31.2 (#3546) * Bumped SDK version and changelog * Added contracts file for 3.31.2 * [Internal] Documentation: Removes invalid comment from ReadThroughputAsync (#3516) * [Internal] nugetconfig: Removes specific overrides (#3551) * Query: Fixes partition range evaluation for spatial queries (#3495) * Initial commit * Update. * Pull/Rebase * Addressed comments. * Build fix * [Internal] Documentation: Refactors cache content on its own document (#3554) * Add cache file * Moving content away * [Internal] Emulator unit tests: Adds IdEncoding unit tests for ComputeGateway (#3556) * Adding IdEncoding unit tests for ComputeGateway * Reacting to code review feedback * Updating md files * Change Feed Processor: Adds support for Resource Tokens (#3566) * Adding rid parsing * Test * Removing dead code * Contract update * [Internal] AI integration: Refactor code how container and database name is flowing to opentelemetry module (#3532) * wip * WIP * Revert "WIP" This reverts commit 71275de54b9e67fa54a37e79d450b9597e173934. * Revert "wip" This reverts commit 586fa9865cc3f40dabd7ef90fb3e0cf499a045bc. * wip add containe and database info * redesign how container and database name information flows into opne telemetry data * test fix * fix test * fix tests * fix typos * baseline test fix Co-authored-by: Sourabh Jain * [Internal] AI Integration: Adds a new flag in DistributedTracingOptions (#3562) * add flag in diagnostic options * test fixes * rename variable * test fix * add validation * fix baseline * test fix Co-authored-by: Sourabh Jain * Query: Fixes default to BadRequestException in case of internal errors in ServiceInterop (#3399) * Don't default to BadRequestException in case of errors in ServiceInterop * Incorporate code review feedback * Fix build error * fix up failing test * [Internal] Query: Adds unit tests for Merge/Split implementation with OptimisticDirectExecution pipeline (#3510) * Added tests to test different aspects of merge/split support with OptimisticDirectExecution pipeline. Tests check for gone exception handling, pipeline switching etc. * Added gone exception simulation tests. * Added new tests and improved test infra * Removed ParalleContEvocation test. Fixed comments * Removed CreateParallelCrossPartitionPipelineStateAsync() as it is not being used anymore * Removed while loop in CreateDocumentContainerAsync() * Fixed comments. * Updated ExecuteGoneExceptionOnODEPipeline() * Added type Assert for ExecuteGoneExceptionOnODEPipeline() * Updated OptimisticDirectExecution pipeline abbreviation * Updated TestBaseline folder with new xml * Client Retry Policy: Adds HTTP timeouts with request-level cross-region retry (#3555) * Fixes to ReadThroughputAsync for databases with no provisioned throughput and null as request options * fixed failure to ReadReplaceThroughputResponseTests * Added Stream Method * Ran UpdateContract.ps1 * Encryption implemtation * Fixed spelling error * Update Microsoft.Azure.Cosmos.Encryption/src/EncryptionDatabase.cs Co-authored-by: Matias Quaranta * Variable name change * Update Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs Co-authored-by: Matias Quaranta * Suggested Changes and fixes * Removed manufactured ResponseMessage + nits * Simplified PR * nits * nits * initial changes TODO: Update tests * updated tests * nits' * Ran UpdateContracts.ps1 * nits + requested changes * Delete NuGet.Config * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/HttpClient/HttpTimeoutPolicy.cs Co-authored-by: Matias Quaranta * Use Cosmos Exception Factory, Simplified Tests * removed unused code * nits: removed unused code * removed unused code Co-authored-by: Matias Quaranta Co-authored-by: Nalu Tripician * Documentation: Fixes EUAP in Comments (#3579) * Query: Fixes incorrect FeedResponse.Count when result contains undefined elements (#3574) * Do not maintain an independent count on QueryResponse that can go out of sync * Add more test coverage for QueryResponse.Count * Output the correct count from CosmosElementSerializer when the input contains CosmosUndefined * Add untyped tests for CosmosUndefined * Remove commented code * removed allr eference (#3581) Co-authored-by: Sourabh Jain * Trace: Fixes Tracing/diagnostics hour-times to 24Hours (#3577) * Trace: Fixes Tracing/diagnostics hour-times to 24Hours * fixing baseline tests Co-authored-by: Matias Quaranta * AI Integration: Adds cosmetic fixes (#3576) * wip * status code int and internal and client kind activity * remove unused imports * update baselines * fix test * fixed baseline tests * fix tests * update base tetss Co-authored-by: Sourabh Jain * Query: Adds ALL Scalar Expression (#3509) * Add SqlAllScalarExpression to v3 DOM * updated generated parser files * Parsing for ALL * Added tests for ALL and baselines * Added more tests * added new test, cleanup * cleaning & fix typos * fixed typo * Added new baseline test file names to csproj file * renamed AggregateAll to AggregateSubquery to accomodate FIRST and LAST later * Added keywords for 'left' and 'right' and respective function calls * fixed bug from last commit * cleaning * replace tabs with spaces * cleaning * Release: Adds API contracts for 3.31.2-preview (#3586) * [Internal] sccignore: Adds a .sccignore file to apply an exception for artifacts configuration issues (#3589) * [Internal] PermissionTests: Adds CosmosPermissionTests Coverage (#3593) * Ensures that both Direct and Gateway connection modes are tested * Validates that container read works with PermissionMode.Read (test was previously only validating that Delete was blocked - i.e. the negative case). * [Internal] AI Integration: Refactors to Operation prefix and add tests (#3583) * add tests for otel and custome listener * clean up * null pointer fix * fix tets * handle event generation also at operation level * added documentation * wip * change event sourcename * rename event Name Co-authored-by: Sourabh Jain * [Internal] HttpTimeoutPolicy: Removes Data Plane Writes from being able to be retried (#3607) * data plane writes no longer failover on timeout * removed duplication of test\ * [Internal] Performance Testing: Adds Distributed Tracing option in benchmarks (#3611) Co-authored-by: Sourabh Jain * [Internal] Benchmark: Refactors code to make Memory Stream capacity configurable (#3624) Co-authored-by: Sourabh Jain * add new LatestVersion changefeed mode that has same behavior as Incremental; renamed FullFidelity to AllVersionsAndDeletes (#3596) * Query: Fixes handling of CosmosUndefined, CosmosGuid and CosmosBinary in unordered DISTINCT (#3632) * Handle CosmosUndefined, CosmosGuid and CosmosBinary in DistinctMap.UnorderedDistinctMap * Address code review feedback and remove unnecessary allocations from DistinctQueryPipelineStageTests * [Internal] Subpartitioning: Adds updates to test coverage for subpartitioning (#3618) * updates to test coverage for subpartitioning * bug fixes * now useses Assert.ThrowsException * Seperated into multiple tests for clarity * Put MultiHash test into seperate test file * nit * [Internal] ContainerProperties: Fixes version reset when setting PartitionKeyPath (#3637) * Remember previous value * test * [Internal] AI Integration: Adds CorrelationId and Activity Id Attributes for query operation (#3630) * add activityid in Otel attributes * added correlation id * operation type fix * remove test changes * test fix * fix baseline test * rename correlationId * fix tests again * include only not null attributes in test * fixed tests * changefeedxml * test fix * ordering activity in operationname oerder * fix test * review comments * refator header getter setter * clean up Co-authored-by: Sourabh Jain * Documentation: Fixes CosmosClientBuilder.WithConnectionModeGateway parameter description (#3643) * Fixed CosmosClientBuilder.WithConnectionModeGateway documentation * Update Microsoft.Azure.Cosmos/src/Fluent/CosmosClientBuilder.cs Co-authored-by: Ruben Bartelink Co-authored-by: Augsten Co-authored-by: Ruben Bartelink * Upgrade Resiliency: Refactors Implementation for Opening Rntbd Connections to Backend Replicas in Direct Mode. (#3640) * Code changes to refactor implementations for opening connections to all replicas. Fixed test failures due to Direct package upgrade. * Code changes to add poland central region as a part of Regions.cs * Code changes to update contract to reflect new regions. * Revert "Code changes to update contract to reflect new regions." This reverts commit f171b3c1c9889043556ddf96bcd33ccd79565ad9. * Revert "Code changes to add poland central region as a part of Regions.cs" This reverts commit 1aafbf18f6d80e9a92baa301b6b23cf065e4b155. * [Preview] AI integration: Adds IsDistributedTracingEnabled flag as public API to enable/disable this feature (#3598) * make api public for preview * add null check * fix tests * singleton listener initialization * assign null to listeners * fix test * concurrent bag in listener * renamed to LatencyThresholdForDiagnosticEvent * renamed to IsDistributedTracingEnabled * updated xml * update contract * made latency threshold flag internal * fix test * regeneratebaselines * update documentation * rename builder api * add docs * updated contracts and all * doc update * import cleanup Co-authored-by: Sourabh Jain * Change Feed Processor: Fixes behavior with StartTime on Local (#3645) * To UTC * Test * [Internal] Client Telemetry: Refactors code to use base useragent string (#3653) * [Internal] AI Integration: Refactors code to rename event name (#3648) * first draft * rename event name * updated xmls * update files * Region Availability: Adds Poland Central Region For Public Usage (#3656) * Client Encryption: Adds validation code to check if the Key Vault URI provided in wrap metadata is a valid key identifier. (#3642) * Check if the key vault uri provided is a valid Kid * test fix. * update changelog and build props * Update Directory.Build.props * Update Microsoft.Azure.Cosmos.Encryption.csproj * Fixed preview version * Refactor * Update EncryptionDatabaseExtensions.cs * [Internal] Query: Adds Split Support for Ode (#3572) * Added tests to test different aspects of merge/split support with OptimisticDirectExecution pipeline. Tests check for gone exception handling, pipeline switching etc. * Added gone exception simulation tests. * Added new tests and improved test infra * Removed ParalleContEvocation test. Fixed comments * Removed CreateParallelCrossPartitionPipelineStateAsync() as it is not being used anymore * Removed while loop in CreateDocumentContainerAsync() * Fixed comments. * Updated ExecuteGoneExceptionOnODEPipeline() * Added type Assert for ExecuteGoneExceptionOnODEPipeline() * Replaced try-catch with if statement in MoveNextAsync() * Added delegate to access TryCreateCoreContextAsync() * Added check to confirm Ode pipeline is not called in fallback plan * Updated method name from OptimisticDirectExecutionContext() to TryCreateOptimisticDirectExecutionContext() * Using delegate instead of Func<>. * Ode fallback plan always calls Specialized pipeline * Using ServiceInterop/Gateway to get QueryPlan for Specialized Pipeline * Added new test to check handling of failing fallback pipeline * Code cleanup * Added logic for handling non ODE continuation tokens * Moved delegate away from member variables * Added tests for Merge case * Updated method names * Added checks for tryCatch * Updated SetCancellationToken() to use Try * Updated TryUnwrapContinuationToken() * Removed changes in FlakyDocumentContainer.cs * Removed unused imports * Updated comments * Fixed comments and cleaned up test code * Added CosmosElement null check in TryUnwrapContinuationToken() * Removed FlakyDocumentContainer.cs from pull request * Removed unused imports * Updated TryUnwrapContinuationToken() * Update MoveNextAsync() call in OptimisticDirectExecutionQueryBaselineTests.cs * Made MergeTestUtil.IsFailedFallbackPipelineTest a readonly property * Added IsPartitionSplitException() overload to take CosmosElement * Fixed bug regarding syntax error queries * [Internal] AI Integration : Fixes operation type for batch (#3660) * fix op type * fix conflict * CosmosClientOptions: Adds ServerCertificateCustomValidationCallback for Http and TCP (#3636) * Adding ServerCertificateCustomValidationCallback in clientoptions * Adding Server callback for Http and fixing tests * Fixing failing E2Etests * Resolving merge conflicts * Running update contracts script * Running Update contracts script * Running Update contracts script * Reverting the v3 version change * Update based on review comments * Added unit tests * Added remarks for callback delegate * Ran update contracts script * Update based on review comments * Ran update contracts script * Updated unit tests * Making ssl validation function private * Updating test files * Update remarks for sslvalidation public contract * Added emulator tests for server validation Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> * Query: Adds EnableOptimisticDirectExecution flag to QueryRequestOptions (#3664) * Added new flag to QueryRequestOptions to allow customers to use Ode pipeline * Updated comments in QueryRequestOptions.cs * Renamed enabledOde to enableOde * Removed default setting for EnableOptimisticDirectExecution * [Internal] Tests: Removes Direct/HTTPS emulator tests (#3679) * Removing direct/https tests * mppreference * [Internal] Benchmark : Fixes issue with dependency on Cosmos Project (#3673) * users/sourabhjain/benchmarkfix * update pipeline * Revert "users/sourabhjain/benchmarkfix" This reverts commit 81b48f0e47aed7a75540c2c83f62cea98d86824f. * fix compilation error * add parama for preview pkg also --------- Co-authored-by: Matias Quaranta * LocalQuorum: Adds Quorum reads on Consistent Prefix Accounts (#3680) Co-authored-by: DESKTOP-ED57J7H\Prashanth Venkataram * 3.32.0: Adds new SDK version and contract files (#3687) * 3.32.0: Adds new SDK version and contract files * 3.32.0: Adds new SDK version and contract files * Updating changelog version * Updating changelog version * Added more commits to changelog and updated release contract * Added documentation tags PR in changelog * Updated changelog based on reviews * Updated PR decsription in changelog * Update changelog.md Updated full fidelity change description Co-authored-by: Matias Quaranta --------- Co-authored-by: Matias Quaranta * [Internal] Samples: Adds change feed pull model samples (#3646) * add change feed pull samples * refactor appsettings validation * addressing pr comments * move task delay * update sample to use latest change feed mode names --------- Co-authored-by: Matias Quaranta * [Internal] Tests: Refactors emulator CI (#3688) * [Internal] GitHub Template: Adds needs-investigation label (#3708) By default, all "Bug report" issues will have "needs-investigation" * Adding fabric bot action (#3709) * CosmosNullReferenceException: Refactors CosmosNullReferenceException to pass along InnerException property on parent NullReferenceException (#3713) * Passed inner exception details to NullReferenceException ctor when instantiating CosmosNullReferenceException. * Added unit tests. * Addressed PR feedback. * [Internal] PriorityRequests: Fixes header value (#3714) Co-authored-by: Matias Quaranta * [Internal] Query: Adds single physical partition check for OptimisticDirectExecution queries (#3699) * Added single physical partition check for Ode queries. Updated test infrastructure for Ode emulator tests too. * Refactored emulator tests to have all the test cases at the top of the file * Updated TryGetTargetRangeOptimisticDirectExecutionAsync() * Uodated logic on how many times CreateIngestQueryDeleteAsync() gets called * Added debug asserts for partitionKeyDefinition * Added pageSizeOptions parameter in CreateInput() in EmulatorTests * Fixed comments * [Internal] CTL: Fixes Reservoir Sampling Logic (#3712) * Code changes to fix the reservoir sampling logic in CTL * Code changes to modify help text on reservoir type. * Code changes to address minor code refactor. * Diagnostics: Adds startDate in Summary (#3707) * Adding start date * Updated trace files * PR comment * Committing missing tests --------- Co-authored-by: Matias Quaranta * [Internal] Client Telemetry: Adds network information in the payload (#3691) * first draft * clean code * add test * fix test * add replica info collection * fix substatuscode and operation type error * fix code * collect http infor in cache also * message to stacktrace * remove rntbd recording from cache * print proper exception message * fix test * cleanup unused code and added few status codes in ignore list * fixed all exception logging * refactor conditions * fix tests * Documentation: Fixes Database.ReadAsync description (#3457) * Documentation: Modify retry time to timespan Modify retry time in seconds to timespan of parameter maxRetryWaitTimeOnThrottledRequests (Method: [WithThrottlingRetryOptions](https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.cosmos.fluent.cosmosclientbuilder.withthrottlingretryoptions?view=azure-dotnet#feedback)) Resolves https://github.com/Azure/azure-sdk-for-net/issues/29567 * Documentation: Fixes DeleteItemAsync Example Documentation: Fixes DeleteItemAsync Example * Documentation: Fixes ItemRequestOptions Example Documentation: Fixes ItemRequestOptions Example * Documentation:Update Database.ReadAsync description Documentation: Update Database.ReadAsync description * Documentation: Update Database.ReadAsync description Documentation: Update Database.ReadAsync description * Documentation: Updated ToStreamIterator example Documentation: Updated ToStreamIterator example * Modified StreamIterator section * Update Microsoft.Azure.Cosmos/src/Resource/Database/Database.cs Co-authored-by: Matias Quaranta * Remarks correction * Revert the StreamIterator changes Revert the StreamIterator changes Co-authored-by: Matias Quaranta Co-authored-by: Kiran Kumar Kolli * Upgrade Resiliency: Adds Implementation for Validating the Unhealthy Backend Replicas in Direct mode (#3631) * Code changes to implement replica validation in dotnet v3 sdk. * Cosmetic changes to add inline code comments. * Code chages to address review comments. * Code changes to cover a scenario for async cache. * Code changes to refactor async non-blocking cache code. * Code changes to address minor review comments. --------- Co-authored-by: Kiran Kumar Kolli * ReadMany: Fixes BadRequest when using Ids with single quotes (#3732) * Use parameters * Emulator tests * Release: Adds SDK version and changelog for 3.32.1 (#3733) * version bump * Contracts * [Internal] Build: Fixes static tool analysis versions (#3736) * Update Binskim and follow warnings * Fixing task * More version bumps * binskim args * Padding * policheck * postanalysis parameters * analysis settings * Query: Fixes System.ArgumentException when using PartitionKey.None on x86, Linux or in Optimistic Direct Execution (#3730) * Minor clean up of OptimisticDirectExecutionQueryTests * More minor cleanup in OptimisticDirectExecutionQueryTests * Add emulator tests for the bypass query parsing scenario * Handle PartitionKey.None while creating QueryIterator. This is a workaround for the PartitionKeyInternal.None not following its own contract * Fix up to correctly handle PartitionKey.None using the CachedContainerQueryProperties * Add more tests where PartitionKey.None maps to PartitionKey.Undefined --------- Co-authored-by: Matias Quaranta * Query: Adds FIRST and LAST Scalar Expressions (#3629) * Add FIRST and LAST objects and update visitors * add FIRST LAST evaluation and update offline engine visitors * Add FIRST and LAST to parser * update another visitor * Fix typo * fix typo * added new tests and baselines * cleaning * cleaning --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: Matias Quaranta * Subpartitioning: Adds support for Prefix Partition Key searches for sub partitioned containers (#3109) * 1st round of changes to support subpartitioning for ChangeFeed * name change and moved a method to FeedRangePartitionKey * support for prefix partition change feed and query including unit and emulator tests. need to verify using FeedRange with QueryIterator * splitting out unit tests from emulator tests * 1st round of changes to support subpartitioning for ChangeFeed * name change and moved a method to FeedRangePartitionKey * support for prefix partition change feed and query including unit and emulator tests. need to verify using FeedRange with QueryIterator * splitting out unit tests from emulator tests * moved logic to choose for prefix partition query and change feed * additional conditional to check for MultiHash partitionkeydefinition kind * removed unnecessary using * cleanup * unnecessary using * removed PREVIEW from proj * unit tests for ResolveFeedRangeBasedOnPrefixContainerAsync * change access modifier * since I changed to static, needed to fix tests * dealing with some testing nits * removed Console.Writeline * slight change in test use containerProperties and partitionKeyDefinition * big fix for resolve feedrange, changes to error behavior, added additional test coverage * test changes * ran updateContracts.ps1 * reverting to 3ad5309e9e22a7376e836cfdbe11fa2438a59133 * Ran Update Contracts * ran updateContracts.ps1 * UpdateContracts.ps1 * updatecontracts * removed bad check from test, removed changes from updatecontracts.ps1 * revert UpdateContracts changes * Reverting to 756a123160d14c424c5e11c4f3520094115aa5d4 * removed accidental change from changelog * removed unwanted change from Directory.build.props * added test clean up * removed console.writelines * updates to query test * removed preview flag * ran UpdateContrats.ps1 * no longer recread feedRange for queries unless using prefix pk * simplified if statement * fixed bug --------- Co-authored-by: Nalu Tripician * [Internal] ClientTelemetry: Adds logic to limit payload size to 2 MB (#3717) * first draft wip fix test and logic * resolve conflicts * limit 2 mb * ad callback * fix tests * code refactor * cosmos json to newtosoft json * clean up files * fix logging to argumrnt based * code refactor * add null check * Query: Fixes regression from LINQ custom serializer fix (#3749) Co-authored-by: Minh Le Co-authored-by: Matias Quaranta * [Internal] LocalQuorum: Refactors override (i.e. strong) to allow from any account consistency (#3753) - Localquorum override (i.e. strong) to allow from any account consistency - Facilitates no-downtime downgrade of existing accounts (i.e. existing Strong/bounded accounts migration to Eventual) * Release: Adds SDK version and change log for 3.32.2 (#3752) * version bump * contract * changelog * version bump * Fixing changelog text * Add another PR * Subpartitioning: Adds APIs for public release and increase REST API version (#3763) * initial commit, Http version issues still needs to be resolved * updateContracts + update Http Version * updateded version in test * update contracts * requested changed * changed name in comments to subpartitioning from multihash * undid changes to TestLiteralSerialization.xml * removed changes to non API.json files * removed non XXXAPI.json file changes * changed verbage on public comments * changed error message to reflect verbage change * Change Feed Processor: Fixes LeaseLostException leaks on notification APIs for Renew scenarios (#3775) * Adding cases * Tests * Upgrade Resiliency: Refactors GatewayAddressCache to Mark TransportAddresses to Unhealthy when Connection Reset Event Occurs (#3768) * Code changes to mark the transport uri to unhealthy for which a connection reset event occures through the connection state listener. * Code changes to bump up the direct version. * Code changes to clean up Gateway Address Cache. * Code changes to fix pipeline build. * Code changes to fix serilization test failures. * Code changes to add force refresh to the gateway function callback delegate. * [Preview] PriorityBasedExecution: Adds PriorityLevel as a RequestOption (#3672) * Added Priority Level as a Request Option * Changed Priority Level Low and High to 1 and 2 respectively * Bumped DirectVersion * Added made PriorityLevel internal for non preview packages * Deleted PriorityLevelTests.cs * Added description of Priority Level in RequestOptions.cs * Modified comments for PriorityLevel in RequestOptions.cs * Updated Contracts * Modified Remarks for PriorityLevel and added see also link. * Updated contracts --------- Co-authored-by: Matias Quaranta * [Internal] Client Telemetry: Adds sampling logic for network level telemetry (#3750) * sampling logic add * throttlinfix * fix tests * fix tests * remove dispose from sampler * add 412 * draft push * refactor code for sampling * clean up * start testing * adding tests * wip * test fix * fix test * fix tests * deleted extra file * remove one toList * add custome logic for sampling * code refactor * replace key * remove commented code from test * added more comments * simpler sampler logic * refactor code * [Internal] Emulator Test : Fixes test when running with distributed tracing enabled. (#3751) * enable DT for everything * try1 * code refactoring * fix pipeline * try 2 * Revert "try 2" This reverts commit 61643f9b4dcd2ab1898fd68b111897bed0bc6bcf. * Revert "fix pipeline" This reverts commit 4b217f5f6a087b1dd889b804fd8b477accd46419. * Revert "code refactoring" This reverts commit d1ff0ddc17ad655360988d171bd033617752f91f. * Revert "try1" This reverts commit bf9c41b43684f59719c3673d6f9c7450bbdc5142. * lazy factory and threadsafe * scope factory in function * try non static * add flag * fix test * add consoles * more console with fix * fix tests * temporarily enable dt * fuix tests * dispose listener * fix tests * remove delay * revert flag change * dynamically get number of test in trace class * Release: Adds SDK version and changelog for 3.32.3 (#3788) * Adding contract and version bump * Adding changelog * SummaryDiagnostics: Refactors Code to Remove Dependency of HttpResponseHeadersWrapper to fetch Sub Status Codes (#3792) * Code changes to fetch sub status code from http response/ content headers. * Code changes to address review comments. * Code changes to return the first element from the sub status list. * Code changes to update first or default. * [Internal] Documentation: Fixes API name to NoSQL (#3795) * [Internal] CTL: Fixes docker image pipeline (#3794) * [Internal] AI Integration : Refactors useragent attribute name as per Otel conventions (#3784) Co-authored-by: Fabian Meiswinkel * HttpClient: Adds Properties to the Http messages if available (#3803) * Passing properties * test * Documentation: Refactors SQL API reference to NoSQL API (#3793) Co-authored-by: Kiran Kumar Kolli * [Internal] Perf test: Refactors code to re-enable performance tests (#3785) * enable perf tests * updated json * upgrade benchmark * update results * updated benchmark results * HttpClient: Adds detection of DNS changes through use of SocketsHttpHandler for .NET 6 and above (#3762) * initial commit * removed unneeded usings * added validation callback, still needs tests * nits + fixes * added additional test * test change * removed unneeded Dispose calls * removed unnneed dispose calls * requested changes * added pooledConnectionLifetime as client option * nit Co-authored-by: Kevin Pilch * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs Co-authored-by: Matias Quaranta * suggested changes * remove test, reorder usings * updated contracts * removed all non XXXAPI.json changes from UpdateContracts run * removed public surface, added random timespan * removed change from unrelated file * Update Microsoft.Azure.Cosmos/src/HttpClient/CosmosHttpClientCore.cs Co-authored-by: Matias Quaranta * added thread safe random method * nit * fixed merge mistake * added reflection failsafe/error tracing * nits * added back removed if * fixed formatting * changed random method, fixed serverCertificateCustomValidation --------- Co-authored-by: Kevin Pilch Co-authored-by: Matias Quaranta * [Internal] Tests: Fixes Open Telemetry attributes for ReadMany test (#3805) * Fixing test * New baseline * Undo some changes * [Internal] Client Telemetry: Refactors code to run client telemetry data processing task in background. (#3783) * first draft * remove failure count test * refactporing * code refactor * create task with timeout * fix test * code refactoring * fix timeout code * space fix * not failing if processor is taking time * fix procrsser test * code refactor * refactor and test fix * Patch: Adds Move Operation (#3389) * Basic changes to introduce move operator * Added "from" object in patch spec operation. Added testcase block. * Fixed testcase. * Changes made to address comments' * Added comment regarding enum mutations * Formatted comment Co-authored-by: Matias Quaranta * Moved summary location. * Ran UpdateContracts.ps1 --------- Co-authored-by: Amaan Haque Co-authored-by: Amaan Haque Co-authored-by: Matias Quaranta * [Internal] Pipelines: Adds nightly build to produce packages (#3802) * Support cleaning * wire previous content delete * as text * with variable * another test * param with types * as string * no delete * no quotes * undoing * re-adding quotes * testing empty * trying another test * readding version * fixing publishing artifacts * fixing parameter * Fixing official pipeline * version 5 * fixing main pipeline * test with true * using start time * nightly preview * passing parameters to pack * Fixing nuget version * arguments on the nuget pack * folder structure * testing v5 * Using only content * Removing currentDate * [Internal] OpenTelemetry: Direct Package update and replacing diagnostic files (#3797) * Direct Package update and replacing dagnostic files * Resolve merge conflicts * Running updateCOnstracts script * Removed LinqTranslationWithCustomSerializerBaseline file * Adding isDistributedTracingEnabled flag * Running update contracts * Running update contracts * Running update contracts * fix test * Code cleanup for test fix * Code cleanup for test fix * Making regex expression readable * Adding comment for regex expression --------- Co-authored-by: Sourabh Jain * [Internal] MerlinBot: Adds auto-merge and cleanup automation (#3813) * Add config changes * Polishing automerge config * Update fabricbot.json (#3824) * [Internal] Upgrade Resiliency: Adds Logic to Validate `Unknown` Replicas along with `Unhealthy`. (#3820) * Code changes to add aggressive validation logic. * Code changes to enable aggressive validation for all regions. * Code changes to pull in msdata cosmos.direct changes related to aggresive validation logic. * Code changes to make minor cosmetic changes. * Code changes to address review comments. * Serialization: Fixes call to CosmosSerializer.FromStream on Gateway mode when EnableContentResponseOnWrite is false (#3814) * Do not call serializer if ResponseMessage.Content is empty. * Add unit test * Update unit tests * Remove unused usings --------- Co-authored-by: Matias Quaranta * [Internal] Documentation: Adds documentation covering build pipelines (#3822) * Add doc * Move benchmark * Fixing texts * Client Encryption: Adds release version of Microsoft.Azure.Cosmos to Microsoft.Azure.Cosmos.Encryption.Custom (#3799) * cosmos version change * changing preview to release * resolving code review comments --------- Co-authored-by: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> * SDK 3.33.0 : Adds version bump and changelog (#3823) * release 3.30.0 * added changelog * updated changelog * updated changelog * suggested change to changelog * updated changelog --------- Co-authored-by: Matias Quaranta * [Internal] Documentation: Adds msdata/direct Sync-up Guide. (#3828) * Code changes to add msdata/direct sync-up documentation. * Code changes to address review comments. * Code changes to address further review comments. * Code changes to address minor review comments. * Removed internal links. * Query: Adds TRIM string system function support in LINQ (#3833) * add trim support * Added some test coverage * address reviews --------- Co-authored-by: Minh Le * Query: Fixes Parsing Error in SQL DOM when CultureInfo is available (#3832) * add fix * Add cultural info to test to verify correct behavior * address pr review to restore to restore culture * fix comment --------- Co-authored-by: Minh Le * Client Encryption: Adds api FetchDataEncryptionKeyWithoutRawKeyAsync and FetchDataEncryptionKeyAsync to get DEK without and with raw key respectively. (#3809) * added raw key to MdeEncryption * adding ray key to Mde Algo * test case changes * resolving code review comments * code optimization to reduce keyvault calls * removed Microsoft.Data.Encryption.Cryptography nuget package * added api for dek with raw key * resolved code review comments * adding change log * code review changes * Initial commit (#3826) * Query: Adds Computed Property SDK Support (#3761) * Initial commit * Restored settings.json changes. * Update * Addressed comments; still need to be tested using Emulator. * Fixes after test run. * Ignored the computed property tests based on the sync this morning (to allow for preview release). * Suite0 fixes. * Test update. * Suite0 fixes * [Internal] Samples: Adds OpenTelemetry and Application Insights samples (#3818) * add opentelemetry and application insights samples * address pr comments * [Internal] Query: Added custom serializer coverage tests to ExpressionToSQL.cs (#3722) * Ensure enum as string is preserved for custom serializer * Failing test * Added failing tests * Updated requested names * Ignore result of test for now * Added additional comment on why the test is ignored * Replaced with sample code * Remove ignore attribute from tests, documented misbehavior for future use * Updated comment --------- Co-authored-by: leminh98 * Query: Added remaining Cosmos Type checking functions to CosmosLinqExtensions (#3724) * Added the remaining Cosmos Type checking functions to the CosmosLinqExtensions * Added comments requested * Updated comment * Updated baseline * Improve readability of dictionary initialization * Aligned with code style guide * Revert change to baseline * Executed update baseline script --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: leminh98 * update sdk version and section tags (#3841) * PackageLicense: Removes PackageLicenseUrl and Adds PackageLicenseFile since PackageLicenseUrl is deprecated (#3847) * proposal to add PackageLicenseFile since PackageLicenseUrl is deprecated. https://github.com/NuGet/Home/issues/4628 * adding attribute Visible=false * making ChangeFeedMode.LatestVersion accessible to the public (#3854) * AI Integration: Fixes Operation Name in the activity and end to end Tests. (#3845) * first draft * second draft * 3rd draft * remove untouched file * test fix * fix order * change order * refactor * skip network activities in test * remove network attributes * SDK 3.34.0 : Adds version bump and changelog (#3855) * SDK 3.34.0: Adds version bump and changelog * adding changelog changes * added a missing PREVIEW PR * Update changelog.md Co-authored-by: Justine Cocchi * Update changelog.md Co-authored-by: Kiran Kumar Kolli * removed 3840 as it was not committed * change text for 3832 * fix merge issue * add 3724 * Update changelog.md Co-authored-by: Matias Quaranta * Update changelog.md Co-authored-by: Matias Quaranta * including 3845 --------- Co-authored-by: Justine Cocchi Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta * Release: Fixes changelog.md change for 3845 to preview (#3859) * removing ThirdPartyNotice.txt from content and contentfiles folders (#3864) * Documentation: Adds see also link to Container.CreateTransactionalBatch (#3860) * Linking limit documentation to Container.CreateTransactionalBatch(PartitionKey) method * Resolved PR comments * Links update * Using learn.microsoft instead of docs.microsoft in the links --------- Co-authored-by: Matias Quaranta * Query: Adds type-markers with count and length for large arrays (#3852) * initial commit * cleanup * update test output * cleanup * typo * Pr comments * [Internal] AI Integration or Open Telemetry: Design Document (#3858) * first draft * redesign * ädd link * updated observability url * Benchmarking: Adds use of ARM Templates for benchmarking (#3838) * initial commit DONT REVIEW * fixes and documentation * Apply suggestions from code review Co-authored-by: Matias Quaranta * requested changes * Apply suggestions from code review Co-authored-by: Matias Quaranta * name changes * readme changes * nits + changing case of parameters file --------- Co-authored-by: Matias Quaranta * Update README.md (#3875) URL typo. * moved to new file (#3876) * Direct Package Upgrade 3.31.0: Refactors code to make compatible with latest direct (#3877) * upgrade to 3.31.0 * add more regions * enable dt for operations * updated contract file * [Preview] Integrated cache: Adds BypassIntegratedCache to DedicatedGatewayRequestOptions (#3836) * Integrated cache: Add BypassIntegratedCache to DedicatedGatewayRequestOptions Currently, integrated cache is used by default for Dedicated Gateway. Customers cannot skip cache for particular requests or data unless they shift to multi-tenant Gateway,which will lose the benefits of Dedicated Gateway. For customers to have more control over integrated cache, we're introducing a new "RequestOption" called "BypassIntegratedCache". This option will allow the customer to decide whether to use integrated cache for each request or not. If this value is set to true, the item/query will be served from backend and won't be cached in Dedicated Gateway. * Move this feature to public preview * Address comments 1. Add more tests 2. Add more detail and example code for BypassIntegratedCache * Revert changes in EncryptionCustomAPI --------- Co-authored-by: Jiajun Peng Co-authored-by: Matias Quaranta * Client Encryption: Adds Microsoft.Azure.Cosmos compatibility to version 3.34.0 (#3874) * chaging Microsoft.Azure.Cosmos support version * resolved merge conflicts * CosmosClient: Fixes missing Trace when converting HTTP Timeout to 503 (#3866) * Added tracing when converting HTTP Timeout to 503 * Fixed tracing when converting HTTP Timeout to 503 * Resolved PR comments * Using ITrace as part of ClientSideRequestStatisticsTraceDatum * Refactoring * Test update * Unit tests fix * AI Integration: Fixes Open Telemetry Example (#3868) * first draft * add filter * revert csproj * fix sample * changed log message * remove unused library * [Internal] Query: Adds OptimisticDirectExecute and RequiresDistribution headers (#3882) * Adding ODE and RequiresDistribution Headers * Fixed comments * Updated parameter in SwitchToFallbackPipelineAsync * Renamed TryUnwrapContinuationToken to UnwrapContinuationToken --------- Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> * Query: Refactors the EnableOptimisticDirectExecution flag to be public (#3883) * Made EnableOptimisticDirectExecution a public flag * Updated contract * [Internal] OpenTelemetry : Adds Telemetry Distributed Tracing functionality (#3801) * Direct Package update and replacing dagnostic files * Resolve merge conflicts * Running updateCOnstracts script * Add code changes for distributed tracing open telemetry changes * Add distributed tracing tests * Updated tests for distributed tracing * Addin traceID for diagnostics * Running update contract script * Removed LinqTranslationWithCustomSerializerBaseline file * Adding isDistributedTracingEnabled flag * Running update contracts * Running update contracts * Updates based on differnt code review comments * Running update contracts * Running update contracts * Running update contracts * fix test * Code cleanup for test fix * Running Update contracts * resolving merge conflicts * resolving merge conflicts * Set EnableDistributedTracing to true for performance tests * Benchmark project change for distributed tracing * Updating tests * Updated unit tests * Updated unit tests * Updated tests and constructors based on review comments * Updated scope name in recorder * Updated distributedOtel tests to cover more scenarios * Updated distributedOtel tests * Reverting benchmark performance test changes * Update DistributedOpentelemetry tests * Update test cleanup * Update distributed tests with custom builder * Update distributed open telemetry tests * Update contracts * Cleanup files * Update distributed Otel tests * Update distributed Otel tests * code refactoring * fix custom listener * Update direct package to 3.31.1 * Code clean up * Update tests with display name --------- Co-authored-by: Sourabh Jain * Documentation: Adds additional remarks to CosmosClient (#3891) * CosmosClient documentation improvements * Cref fix * Link fix * Documentation fix * Typo fix --------- Co-authored-by: Matias Quaranta * Open Telemetry End To End Test: Adds baseline for network level requests trace (#3887) * enable request level in end to end * made some changes * fix tests * fix display name * hardcoded containername and databasenam * fix tests * temp * fix tests * update contracts * fix tests * fixed display name * [Internal] Design Docs: Adds Design Document for Client Telemetry (#3590) * sdk design for client telemetry * Otel design * update optel design * added more nformation * updated ct design * remove otel design * Client Telemetry Design * update typos * fix typos * fix typos * added limitation * updated docs * updated doc * updated text * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * Update docs/observability.md Co-authored-by: Kiran Kumar Kolli * move stuff here and there. --------- Co-authored-by: Kiran Kumar Kolli * [Internal] Design Docs: Adds Design Document for Client Telemetry Part 2 (#3903) * updated doc * Update docs/observability.md Co-authored-by: Justine Cocchi * updated text --------- Co-authored-by: Justine Cocchi * ConnectionPolicy: Refactors Code to Reduce Default Request Timeout to 6 Seconds. (#3902) * Code changes to reduce default request timeout to 6 seconds. * Code changes to update API doc default request timeout to 6 seconds. * [Internal] Upgrade Resiliency: Adds Replica Health State Diagnostics. (#3835) * Code changes to add replica health status in diagnostics. * Code changes to fix performance test build failure. * Code changes to add health state capture logic in address cache. * Code changes to fix benchmark test execution. * Code changes to add tests to validate health state cache. * Code changes to reduce default request timeout to 5 seconds. * Revert "Code changes to reduce default request timeout to 5 seconds." This reverts commit 139f37e588fc9dfed608431f4186c567a080e622. * Subpartitioning: Fixes handling of split physical partitions (#3879) * Initial Commit DO NOT REVIEW * bug fix, needs Direct Package Changes * fix for change feed and query plus tests * clean up * query + clean up --------- Co-authored-by: Kiran Kumar Kolli * [Query] Fixes empty property name parsing exception (#3907) * inital commit * cleanup * test cleanup * PR comments * PR comment * [Preview] Query: Refactors EnableOptimisticDirectExecution to true by default in Preview mode (#3909) * Setting EnableODE to true by default in Preview Mode. * Added seperate if block for default value * Updated property * Removed unused Usings * Updated contracts * Updated test * Updated directive indentation * Documentations: Adds links to PatchItems docs (#3910) * Added links to PatchItems docs * Undo changes from internal file * [Internal] Direct Package Upgrade: Refactors Code to Bump Up `Cosmos.Direct` Package to `3.31.2` (#3918) * Code changes to bump up the direct version. * Code changes to mark the Israel Central region as public. * Code changes to update contracts. * Code changes to fix test failure. Some clean ups. * Code changes to add detailed message for open channels count. * SDK 3.35.0 : Adds version bump and changelog (#3920) * release PR * updated changelog.md * more changelog updates * [Internal] Last minute fix to changelog for 3.35.0 (#3921) * release PR * updated changelog.md * more changelog updates * changelog fix * Update changelog.md * Update changelog.md * [Internal] Query: Adds new header SupportedSerializationFormats (#3911) * Binary Serilaization Response test * Added new header SupportedSerializationFormats * Modified existing use of CosmosSerializationFormatOptions * Modified tests and removed unused code * Addressed comments * Added more negative cases * Revert changes * Added spaces * Addressed comments * Addressed comments * Removed SupportedSerializationFormats from Headers file * Removed unused JsonSerilazationFormats option * Addressed comments * Addressed comments * Addressed comments * Addressed comments * Added new enum TransportSerializationFormat * Added new enum TransportSerializationFormat * Addressed comments * Removed unused parameter * Addressed comments * updating API * remove tests * Text fixes * fix typo * remove TransportSerializationFormat header * text reverts * revert * test update * PR comments * remove test owner headers HeadersValidationTests.cs * PR comments - remove unsupported tests and scope client --------- Co-authored-by: Heet Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: Matias Quaranta * Code changes to optimize the rntbd open connection logic to open connections in parallel. (#3939) * Query : Adds support for newtonsoft member access via ExtensionData (#3834) * Support newtonsoft member access via ExtensionData * Return null instead of empty string * Added tests for select & where * Updated baseline with note --------- Co-authored-by: leminh98 * HttpTransport: Fixes HttpTimeoutPolicies to not accidentally suppress retries (#3944) * Fix HttpTimeoutPolicies to not accidentally suppress retries * Removing HttpTimeoutPolicy.MaxRetryTimeLimit altogether * SDK 3.35.1 : Adds version bump and changelog (#3945) * version bump * changelog * contract * [Internal] Changelog: Fixes recommended version and title (#3948) * SDK 3.35.1: Adds version bump and changelog * Update changelog.md * Update changelog.md * Update changelog.md * Update changelog.md * Update changelog.md * [Internal] Dependencies: Fixes dependabot alert for System.Linq.Dynamic.Core (#3957) * Removing 1 * Removing 2 * Removing 3 * [Internal] Upgrade Resiliency: Adds Code to Enable Replica Validation Feature for Preview (#3951) * Code changes to add replica validation feature in cosmos client options. * Code changes to upgrade the cosmos direct version to 3.31.3. * Adding emulator test to cover replica validation. * Code changes to address cosmetic clean ups. * Code changes to address review comments. Fixed preview build failures. * Code changes to enable replica validation for preview package by default. * Code changes to address review comments. * Code changes to fix preview unit tests. * Code changes to disable environment variable at the end of the test. * Client Encryption: Adds package reference Microsoft.Azure.Cosmos version 3.35.1-preview (#3956) * changing cosmos preview version * updating build file --------- Co-authored-by: Matias Quaranta * [Internal] FabricBot: Adds GitOps.ResourceManagement because of FabricBot decommissioning (#3966) * Add prIssueManagement.yml to onboard repo to GitOps.ResourceManagement as FabricBot replacement Owners of the FabricBot configuration should have received email notification. The same information contained in the email is published internally at: https://aka.ms/gim/fabricbot. Details on the replacement service and the syntax of the new yaml configuration file is available publicly at: https://microsoft.github.io/GitOps/policies/resource-management.html Please review and merge this PR to complete the process of onboarding to the new service. * Deleting fabricbot.json --------- Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> * [Internal] Query: Refactors certain tests to not fail when EnableOptimisticDirectExecution is set to true in 3.35.0-preview package (#3955) * Updated emulator and baseline tests to not fail when ODE is set to default true in PREVIEW mode * Fixed QueryAsync() test * Fixed QueryAsync() in EndToEndTraceBaselineTests * Undid changes to IndexMetrics baseline file * Updated EndToEndTraceWriterBaselineTests.QueryAsync xml * Updated xml * Updated xml to have request options tag * Diagnostics: Fixes verbose levels for "Operation will NOT be retried" (#3969) * Query: Fixes malformed continuation token exception type and message (#3917) * Fixed malformed continuation token issue where Exception was not CosmosExceptionan and did not have the correct Status and Sub Status codes. * Fixed incorrect indentation * Added type check for incoming exception * Replaced if/else with extra catch block * Moved fix to a higher point in the call stack * Removed unused Usings * Updated test code --------- Co-authored-by: Matias Quaranta * [Internal] Upgrade Resiliency: Refactors Code to Enable Replica Validation Feature Through `CosmosClientOptions` And Environment Variable (#3974) * Code changes to use client options to enable or disable replica validation. * Code changes to fix preview build failures. * Query : Adds string comparison alternative when converting LINQ to SQL (#3668) * string.Compare supported with LINQ to SQL * Update tests * Update test name * Update tests * Add test * Create helper ReverseExpressionTypeForStrings * PR feedback * Update tests * Update base line --------- Co-authored-by: Aditya Co-authored-by: Matias Quaranta * AI Integration: Fixes event generation for failed requests (#3973) * first draft * fix code * included feedback * flip condition * updated docs * Update docs/observability.md Co-authored-by: Matias Quaranta * Update observability.md * updated contract --------- Co-authored-by: Matias Quaranta * [Internal] Category: Refactors Cosmos benchmark operations (#3961) * Refactoring: base classes for operations. * Updating comments. * Adding new line at the end of the file. * Fixing code review points. * Restore PrepareAsync to be virtual. * 3.35.2: Adds new SDK versions and contract files (#3985) * Updated change log and bumped up the version. * Changing the version to 3.35.2 * Code changes to address review comments. * Code changes to make minor fixes. * Code changes to move some fixes into preview. * [INTERNAL] LocalQuorum: Adds documentation for LocalQuorum (#3993) * Draft of local-quorum documentation * Adding experimental to header * Adding cross-region read guarantees * Reads Bounded clarification * Adding account consistency step also * Non-Prod usage note at top * Addressing review comments * Some more refinement * Code changes to update release note. (#3996) * Client Encryption: Adds fix for supporting Prefix Partition Key (Hierarchical partitioning) (#3979) * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * Hirarchical pk bug fix * testing new version * adding more tests * adding more tests * adding more tests * code review changes * test fix * test fix * test fix * test fix --------- Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> * Query: Refactors changelog.md with Optimistic Direct Execution recommendation (#4004) * Update changelog.md This is a recommendation for customers if they would like to use the ODE features. * Updated release notes for ODE * [Internal] Query: Adds performance testing for OptimisticDirectExecution pipeline (#3839) * Infrastructure for performance testing with ODE pipeline. * Resolve comments * Removed randomization from data creation process * Fixed comments * Removed Query and EnableODE from QueryStatisticsMetrics, as they do not relate to query statistics. * Removed try catch to make CreateItemAsync call always succeed * Removed one liner functions * Removed code from MetricsSerializer and QueryStatisticsDatumVisitor files * Fixed comments * Removed request Charge check * Bug in Debug Assert * Test * Bug in debug assert fix * Fixed second bug in Metrics Accumalator class * Added ignore flag to ode perf tests so that they do not run on every loop build * Added comment explaining the Ignore flag. * Query: Adds ODE continuation token support for non-ODE pipelines (#4009) * Added code to throw exception if ODE continuation token goes into non ODE pipeline * Removed count variable * Updated test name * Removed ODE continuation token logic from caller class * Simplified code * Fixed comments * Updated continuation token cast * Removed const string for continuation token * Added Ignore flag for test * Added baseline test * Updated baseline test * Code changes to disable replica validation in preview package. (#4019) * 3.35.3: Adds new SDK versions and contract files (#4024) * Updated change log and bumped up the patch version. * Code changes to update the change log message. * [Internal] Distributed tracing: Adds a sample to collect activities and events using custom listener (#4021) * custom listener example * removed unwanted code * add comments * fix appsettings * revert changes * Code changes to fix race condition by calling dispose too early. (#4030) * Code changes to update change log for release 3.35.3 (#4032) * Documentation: Fixes article links (replaced links V2 to V3 SDK version) + Azure Cosmos DB typo (#4031) * Documentation link fix * Fixed Typo "Azure CosmosDB"→"Azure Cosmos DB" * [Internal] Benchmark tool: Adds Cosmos Benchmark Metrics (#3950) * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Fixing code review points. * make MetrcisCollectorProvider non static and remove locks * fix * fixes * use static class name TelemetrySpan.IncludePercentile * use app insights connection string * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * rename AppInsightsConnectionString * fix * fix comments * fix if AppInsights c string is not set * summary * fix * remove unnecessary collector types * remove unnecesary metere provicer * add event source * remove folder * fix * split success and failed latencies * fix * fix --------- Co-authored-by: David Chaava Co-authored-by: David Chaava * GatewayAddressCache: Fixes Unobserved Exception During Background Address Refresh (#4039) * Code changes to fix unobserved exception during background address refresh. * Code changes to add exception handler in task. * Code changes to fix null ref exception. * Revert "Code changes to fix null ref exception." This reverts commit 83f90d578bd301339f6fa13981a0fe2fc3d65fa6. * Revert "Code changes to add exception handler in task." This reverts commit c49ed8162758217a09df28417a6f76649eab6a26. * Code changes to address review comments. * Revert "Code changes to address review comments." This reverts commit d2b9f6b501f64f1a50b8a49de3ea76fbb9b5c853. * Documentation: Adds additional note for GetContactedRegions method (#4042) * Added small remark for GetContactedRegions method documentation * Moved to remarks * [Internal] Client Telemetry: Adds Client Telemetry pipeline sending data to service (#3900) * first draft * comment other pipelines * pint variables * commnet other pipelines * added env variable * minor changes * update env variable * print env variable * add space in end * fix test * fix tests * fix test * fix tests * remove response interceptor * logs * debuug mode * 3failing test to print llgs * minor refactoring * 2nd windows-2019 * fix ct tests * 2remove debugging * fix tests * revert * ncomment pipelines * fix test * minor changes * release and emulator pipeline * update pipelines * ignore abstract class test * fixing pipeline * refactor code * change it to class name to run tests * added emulator setup * 1 temp commit * env variable * renames env variable * fix tests * add condition * fix tests * reorder env variable * revert pipeline * did some clean up * change to revert * Revert "change to revert" This reverts commit 03db3c104505dc7b8f3cea267835c92ca530f8f4. * fix typos * throw if exception intercepter is null * remove modelling changes * removed virtaul * Update Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/HttpHandlerHelper.cs Co-authored-by: Matias Quaranta * added condition for pipelines * Revert "added condition for pipelines" This reverts commit f9a208cd28e01badee97a2eb770a486cea67c1f0. * changed cond * fix codn * more enhancement * testing for release pipeline * refactore code and using test category * added comments on test * refactor pipeline code * fix variables * fix pipeline --------- Co-authored-by: Matias Quaranta * [Internal] Client Telemetry: Refactors code for collectors (#4037) * refactored code * implemented review comments * test fix * fix tests * fix test * fix test * logger fix * update contract * fic test * updated benchmarks * [Internal] Automation: Adds logic to tag customer-reported issues (#4047) * Added customer-reported label * Changing condition * padding * more padding * permission name * padding * [Internal] Benchmark tool: Adds requests diagnostic data capture and upload to storage (#3926) * azure-cosmos-dotnet-v3/issues/3889 add diagnostics data capturing during bechmark and storing into blob storage after finish * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh * fix bug * fix review comments * fix comments * fix comments * fix case * add tests and refactoring * fix * unify logging * add summaries * fix method summary * fix BOM * fix review comments * fix comment * fix line breaks * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * catch exceptions * add container prefix * ResultStorageContainerPrefix * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/custom-script.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs Co-authored-by: Kiran Kumar Kolli * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json Co-authored-by: Matias Quaranta * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs Co-authored-by: Kiran Kumar Kolli * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Fx/DiagnosticDataListener.cs Co-authored-by: Matias Quaranta * fix comments * fix comments * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * make BlobCLient Lazy singleton * new file: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/azuredeploy.json * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/scripts/execute.sh * check on diagnostic colletiong * remove locks and improve logs appending * removed unnecesary directory * removed unnecesary directory * removed unnecesary directory * new file: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/ARMTemplate/README.md * add dashboard * fix arm template * change branch * fix * add dashboard name * fix dashboard * add logging * fix * trace error * fix devide zero * add trace errors * fix * fix * fix * fix * fix * migrate to text writer * fixes * diagnostic logs * add diagnostic logs * remove flush and reset * metric collection window lock * collection window * force flush every n seconds * fix bug * fix * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/README.md Co-authored-by: Matias Quaranta * change deafult metric interval * constant * fix container creating conflict issue * change azuredeply branch name * remove ArmTemplate folder * fix DiagnosticLatencyThresholdInMs default value --------- Co-authored-by: David Chaava Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta * [Internal] Benchmark tool: Adds feature to the dashboard that generate plots queries for metrics with a workload name prefix, depending on the benchmark workload type. #4048 (#4053) * Merge remote-tracking branch 'origin/master' into users/v-dchaava/benchmark-diagnostics/3889 * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/AzureVmBenchmark/README.md * add metrics prefixes * fix chart metrics names * fix dashboard queries according selected workload type --------- Co-authored-by: David Chaava * [Internal] Client Telemetry: Adds client config api call to get latest flag status (#4050) * first draft * tets fix * fix dependent projects * reduce refresh time in tests * fix tests and added comments * fix diagnostic handler fix * fix test * adding test * ret pushmove console * fix test * provide options to enable/disable this featire in benchmark and ctl proj * updated trace message Co-authored-by: Matias Quaranta * remove import * updated traces Co-authored-by: Matias Quaranta * test fix * remove null assignment * fix test --------- Co-authored-by: Matias Quaranta * [Internal] Benchmark tool: Fixes benchmark run command using OSSProjectRef parameter (#4066) * fix benchmark run command using OSSProjectRef parameter * remove ShouldUnsetParentConfigurationAndPlatform=false --------- Co-authored-by: David Chaava * [Query] Adds public backend metrics property to Diagnostics (#4001) * initial commit * some pr comments, WIP * Refactor * more * Public constructors and modify accumulators * accumulator updates and undo test changes * add test * PR comments * bug fix * ToString() refactor * contract updates * test updates * small fixes * text fix * Update accumulators * fix * PR comments * small fix * Rename BE -> ServerSide * more renaming * Update API and tests * separate public and internal classes * API update * change namespace * Pr comments * public constructors and bug fix * API updates * renaming and test updates * PR comments * more PR comments * PR comments, test additions * API updates and more tests * tests and pkrangeid update * PR comments * more PR comments * smol test fix * PR comments - renaming properties and constructor rehash * contract update * seal classes and private fields. * update indexHitRatio calc * mocking refactor to abstract classes * contract updates * PR comments - Update documentation * [Query][Internal] Adds tests for aggregate queries with invalid continuation tokens (#4052) * partial test * Tests and error handling update * update error message * typo * update original err msg * combine tests * test cleanup * undo error message update * [Internal] Benchmark tool: Fixes code refractoring to model the metrics as EventSource (#4040) * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Adding metrics for Benchmark tool. * Adding OpenTelemetry. * Revert "Adding OpenTelemetry." This reverts commit c7da0884697064103145099e284892365f4ebb68. * Telemetry for windowed percentiles. * OpenTelemetry, AppInsights and Dashboard. * Removing DiagnosticDataListener. * Code styling, comments and clean-up. * Fixing issues with dashboard. * Fixing positions of charts on the dashboard. * Fixing the dashboard. * Updating titles and subtitles. * Removing ILogger and other not required references. * Fixing code review points. * Fixing issues after rebase. * Removing unnecessary changes. * Fixing code review points. * Fixing code review points. * make MetrcisCollectorProvider non static and remove locks * fix * fixes * use static class name TelemetrySpan.IncludePercentile * use app insights connection string * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * modified: Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs * rename AppInsightsConnectionString * fix * fix comments * fix if AppInsights c string is not set * summary * fix * remove unnecessary collector types * remove unnecesary metere provicer * add event source * remove folder * fix * split success and failed latencies * Code refractor to use EvenSource design pattern for metrics * Fixing build breaks * Removing BenchmarkExecutionEventSource * Fixign misc things * Some extra cleanup * use TimeSpan except milliseconds * fix metrics publication * fix metrics publication * move tests to benchmark folder * move back benchmark test * use background task for flushing metrics * remove sync metrics flushing * split failed and success operations * fix latenclies charts * fix benchmark run command * remove ShouldUnsetParentConfigurationAndPlatform=false --------- Co-authored-by: Mikhail Lipin Co-authored-by: David Chaava Co-authored-by: David Chaava * first draft (#4079) * Subpartitioning: Fixes bug for queries on subpartitioned containers (#3934) * initial fix, needs testing on prod * test fix * clean up pr * query rework * refactors previous changes * requested changes and bug fixes * nits * requested changes * bug fixes * start of test * added test * nit: changed name of EffectivePartitionKeyRanges to EffectiveRangesForPartitionKey * Address code comments * Address code comments * saving work * addresses code comments * nit, spacing * PartitionKeyHash fixes * Fixes bugs in tests * Removed bad method, added additional test coverage * Removed EffectivePartitionKeyString use * test fix * requested changes * Requested changes * fixed test * Test fix * Added comment --------- Co-authored-by: SrinikhilReddy * [Internal] Query: Fixes LINQ Test Organization (#4076) * preliminary change * Add some more boiler plate code * move all linq test to the same folder; add some groupBy test * fix references error in test refactoring add code for group by substitution. Still need to adjust binding post groupby * preliminary for the groupby functions with key and value selector * trying to change collection inputs for group by * Undo the LINQ GROUP BY part * fix accidental changes --------- Co-authored-by: Minh Le * ClientTelemetry : Adds logic to call client config in every 10 minutes (#4071) * first draft * fix tests * fixes * fix tests * remove consoles * added exception * remove comment * fix tests * fix test * rev comments * rev comments * refactor code * remove log from api exception * SDK 3.35.4: Adds version bump and changelog (#4087) * bump version and changelog * added apis * Update changelog.md * [Internal] Query: Fixes escaped string parsing in SqlParser (#4054) * Initial commit * Addressed comments. * Bechmark : Fixes benchmark runs (#4088) * pk to result container * set pk * pk value fix * update run.sh * remove changes value * remove telemetry service end point * cleanup * [Internal] Query: Adds Index Metrics V2 Object Model (#4058) * making necessary ownership change * made change to ownerships * header test * Call to TryCreate instead of Create in Responsemessage * Add baseline test infra for index metric parser * update baseline files * Add parse retry logic * Update headers test * address code review * address code review * fix tests * Update csproj file * Adopt the new header * update the response to parse with text instead of base 64 * test for headers adoption of uri escape * Add URI Decode logic * Update baseline * Update with the new header name from back end * update the query parsing requirement * New Index Metrics DOM * fix build error * Code clean up * Address code review * Turn off switching to V2 * Fix test * fix test errors * Address code review comment * addressed code review * removed the empty entity * update test parse * update test --------- Co-authored-by: Minh Le * Distributed Tracing: Fixes dependency failure on appinsights (#4098) * first draft * refactor * fix tests * fixed condition * [Internal] Query: Adds deserializing logic for ClientQL Coordinator Distribution Plan (#3988) * First commit. * Added remaining classes for ClientQL structure * Added ClientQLDeserializing class and added CoordinatorDistributionPlan folder * Added support for all Enumerable and Scalar Expressions * Added baseline tests for testing CoordinatorDistributionPlan deserializing * Made ClientQL objects immutable * Added error and null checks for Value calls * Updated List<> with IReadOnlyList<> * Made most functions in the Deserializing class private and static * Added static constant class for Enumerable expressions * Added null checking for arrays * Removed null checks from deserializing array functions * Removed support for JavaScript * Removed support for Unwind * Function names changed * Removed few functions. * Updated constants class * Function Formatting for ClientQL Deserializing (#4062) * Adding error handling for Deserializing functions * Finished updating code to remove all dependency on Newtonsoft.Json * Removed try catch for all upper level functions * Resolved comments * Resolved comments pt2 * Updated error message * Resolved comments pt3 * Changed parameter types from int to long * Removed ClientQLDelegate * Syntax Fixes * Removed ClientQLFlattenEnumerable file. This is JS. * Fixed List helper functions * Made singleton constructors from public to private * Updated the DeserializeClientQLBinaryLiteral function * Renamed ClientQL to QL * Fixed variable names * Updated more variable names * Removed support for Type * Removed all extra newlines * Added null checks * Updated the name CoordinatorDistributionPlan to ClientDistributionPlan * Removed all support for Cassandra, Mongo and Binary Literal * Updaed ClientQL to Cql * Updated baseline test class property. * [Internal] Query: Adds check to detect unsupported queries for Optimistic Direct Execution code path (#4090) * Added query validity function on Ode code path * Fixed syntax * Updated to use string search instead of query parsing * Updated string search to now be regex * Changed location of caller for QueryValidityCheck() * Updated regex string * Added extra test coverage * Added const string to error messages * Added compile flag to Regex * Fixed comments * Added missing null reference coverage * Removed extra foreach loop in test * Removed useQueryPlan bool in test code * [Internal] Query: Fixes minor issues with TestQueryValidityCheckWithODEAsync (#4105) * Fixed typos and made test more readable * Another typo * Query: Adds LINQ RegexMatch Extension method (#4078) * Add support for translation to REgexmatch * Add test and fix some indexing issues * remove visit explicit, add some comment. Update public contract and added the baseline for the test * add the missing baseline * added test * address code review * update csproj --------- Co-authored-by: Minh Le * Chaning Bounded to Strong (#4103) * Client Telemetry: Adds new public APIs (#4056) * Revert "[Internal] Client Telemetry: Refactors code for collectors (#4037)" This reverts commit e2311a9fdcca392ec7d49c13939aaff3404deb85. * Revert "Revert "[Internal] Client Telemetry: Refactors code for collectors (#4037)"" This reverts commit f04234b76174180b482eadfa0f6f412c80d380c3. * firdst draft * initialize object * null handle * update contracts * compilation charges * fix tests * public API changes * add docs * contract updated * fixed tests * by default switch of te;emetry in sdk * fix tests * fix assertion * incorporate review comments * fetaure flag fix in script * switch case * add test * fix tests * fix test * fixed run.sh * minor changes * code refactor * changed default values and fix tests * [Internal] Build: Adds CodeQL support in nightly builds (#4113) * Update azure-pipelines-nightly.yml * Newlines in variables sections * Benchmark: Fixes to show estimated cost of a container only when new container is getting created (#4109) * Showing Estimated Cost only when new container is getting created * read container to get container response * disable client telemetry by default * removed unused imports * resolve merge conflict * fixed name * fix container not found * removed the message * Update Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/Program.cs Co-authored-by: Matias Quaranta * removed line space --------- Co-authored-by: Kiran Kumar Kolli Co-authored-by: Matias Quaranta * Distributed Tracing: Fixes SDK responses compatibility with opentelemetry response (#4097) * adding tets * wip * wip2 * fix code * add tests * fix test * fix test * remove consoles * fix indent and remove unused imports * internal to private rollback * added docs * removed unused imports * added exception in message * fix exception catching * Revert "Query: Adds new system strings in JsonBinaryEncoding, replacing 1-byte user strings (#3400)" (#4108) This reverts commit 9140890d788cd43d5668d12072be6b965995a28a. * CosmosClientOptions: Adds support for multiple formats of Azure region names (#4016) * Allow ComosClientOptions to take ApplicationRegion and ApplicationPreferredRegions in multiple region name formats. This is a proposed fix for - https://github.com/Azure/azure-cosmos-dotnet-v3/issues/2330 * Address PR comment to avoid duplicating list of names. * Remove the map table cache The map table is only used on initialization, so there's no need to keep a cache of it for the lifetime of the application * Only convert the region names when the client is initializing The cache is created before converting all the names, so it only needs created once, but doesn't remain for the entire lifetime of the application * Update tests * Make RegionNameMapper an instantiable class Instead of having a prepare/clear cache system on a static class, make RegionNameMapper a class that gets instantiated for use and let the ctor handle it. * Remove debugging * Update tests to actually test things --------- Co-authored-by: Pradeep Chellappan Co-authored-by: Pradeep Chellappan <94089783+pradeep-chellappan@users.noreply.github.com> Co-authored-by: Matias Quaranta Co-authored-by: Kiran Kumar Kolli * Distributed Tracing: Fixes traceid null exception issue (#4111) * Fix traceid null exception issue * Fixing merge conflicts * Fixing merge conflicts * Update script * Code cleanup * Updated change description * updated comment description * updated comment description --------- Co-authored-by: Matias Quaranta * Telemetry Options: Adds telemetry options in GA package (#4117) * GA telemetry options and updated contract * enabe requuest level option * added request option in public contract * [Internal] Direct Package: Adds version bump (#4120) * direct version bump * Code changes to fix emulator tests to comply with direct release 3.31.5. --------- Co-authored-by: Debdatta Kunda * Query : Adds Missing QueryMetrics Documentation (#4127) * Update ServerSidePartitionedMetrics.cs * Update ServerSidePartitionedMetrics.cs * TriggerOperation: Adds Upsert Operation Support (#4119) * Added Upsert Trigger Operation Support * updated contract * fix test * SDK 3.36.0 : Adds version bump and changelog (#4118) * first draft * updated changelog * remove already released PRs * updated pr links * changelog and contract changes * updated changelog * updated changelog * updated changelog * remove 4071 from changelog as it should be internal PR * removed an query internal log * updated contracts * Release 3.36.0: Fixes pipeline by removing ReleasePackage variable (#4130) * remove release variable * revert build config variable change also * Item Operations: Fixes JsonSerialization exception when MissingMemberHandling = Error on Json default settings when NotFound on Item operations. (#4125) * issue 4115 initial checkin. need insight from issuer on reproducing this issue * test refactoring and adding more coverage for other NotFound scenarios * commit on some actionables * setting JsonConvert.DefaultSettings to null so that other tests will not fail * as requested, removed catches from test methods * [Internal] Query : Adds test coverage for custom serializers (#4114) * initial cleanup * test updates - working * cleanup * more cleanup * more * whoops * Add results to basline * adding payload to xml * some generics * cleanup * Add datamember serializer * reorder functions and test fix * tostring() update and add case * fix payload * fix datamembertest * cleanup * cleanup * PR comment --------- Co-authored-by: Matias Quaranta * Release 3.36.0 : Fixes Client Telemetry Release Test (#4132) * Client Telemetry Release test fix * get endpoint from env variable * read client telemetry endpoint service from env * updated yaml * Update CosmosItemTests.cs (#4141) * Release 3.36.0: Fixes client config test and preview pipeline (#4149) (#4150) * Fixed client cpnfig test and preview pipeline * fix telemertry service step * Query : Fixes querying conflicts (#4100) * Initial commit * Update * Updated the test * Updated the test * Sample fix; to validate Suite0. * Skipped the ConflictsTest (which depends on azure cosmosdb account) * Addressed comments * Added Unit Test. * Reverted unnecessary change. * Fixes changelog typo and date (#4155) * Bump Azure.Identity in /Microsoft.Azure.Cosmos.Samples/Usage/Encryption (#4136) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.5.0 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.5.0...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Matias Quaranta * Bump Azure.Identity (#4135) Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.5.0 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.5.0...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Per Partition Automatic Failover: Fixes Gateway 503 Cold Start Issue (#4073) * Code changes to add retry logic for GW returned 503.9002. * Revert "Code changes to add retry logic for GW returned 503.9002." This reverts commit 53ef5f3c1b038d14dbb1473cafa18223b33af2ce. * Code changes to clean up the PPAF retry logic fix. * Code changes to add retry logic for GW returned 503.9002. * Revert "Code changes to add retry logic for GW returned 503.9002." This reverts commit 53ef5f3c1b038d14dbb1473cafa18223b33af2ce. * Code changes to clean up the PPAF retry logic fix. * Code changes to revert location cache changes. * Code changes ro revert location cache changes. * Code changes to fix some of the failing tests. * Code changes to fix unit tests. * Code changes to add unit tests for client options. * Code changes to draft docs for PPAF design approach. * Code changes to add SDK side design docs for PPAF. * Code changes to modify the PPAF design. * Code changes to fix unit test. * Code changes to rename test name. * Code changes to add some cosmetic changes. * Code changes to enable retry on write for all regions in single master accounts. * Code changes to add code comments. * Code changes to clean up and handle endpoints in location cache. * Code changes to fix unit tests. Added detailed code comments. * Code changes to clean up the account read endpoints generation logic. * Code changes to fix unit tests. * Code changes to disable retry when ppaf is not enabled. Also validated application preferred region. * Code changes to fix unit tests. * Code changes to update md file. * Code changes to remove chache expiry check for account read endpoints. * Code changes to fix unit test. * Code changes to fix more tests. * Code changes to address review comments. * Code changes to fix verbaige in design document. * [Internal] Query: Fixes optimalPageSize logic for OFFSET LIMIT in ORDER BY queries (#4158) * Fix logic in CosmosQueryExecutionContextFactory where we determine optimal page size for ORDER BY queries that have an OFFSET/LIMIT clause. Previously, the logic was only being applied to TOP and not OFFSET/LIMIT. * Changes based on PR feedback * Change based on PR feedback * [Internal] Client Telemetry: Adds telemetry contract (#4161) * add tests * fix tests * remove unreated files * Client Encryption: Adds Azure.Identity from 1.1.1 to 1.10.2 (#4134) * Bump Azure.Identity in /Microsoft.Azure.Cosmos.Encryption.Custom/src Bumps [Azure.Identity](https://github.com/Azure/azure-sdk-for-net) from 1.1.1 to 1.10.2. - [Release notes](https://github.com/Azure/azure-sdk-for-net/releases) - [Commits](https://github.com/Azure/azure-sdk-for-net/compare/Azure.Identity_1.1.1...Azure.Identity_1.10.2) --- updated-dependencies: - dependency-name: Azure.Identity dependency-type: direct:production ... Signed-off-by: dependabot[bot] * Update Microsoft.Azure.Cosmos.Encryption.Custom.csproj Updated the Azure.Core version --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> Co-authored-by: Matias Quaranta * [Internal] Query: Removes ForcePassThrough support (#4160) * Remove passThrough from the codebase * Updated TestOptimisticDirectExecutionQueryAsync() to remove all aspects of passThrough from it * Undoing previous change * Removed forcePassThrough from FullPipelineTests.cs * Undoing changes to remove PassThrough * Undoing passThrough removal pt2 * Undoing changes to SanityQueryTests.cs * Updated TestTryExecuteQueryHelper() * Updated comment * Changed boolean location * Removed TryExecuteQueryAsync() * Fixed indentation * [Internal] Upgrade Resiliency: Fixes Duplicate Channel and Task Creation. (#4123) * Code changes to fix duplicate channel and thread pool on refresh flow. * Code changes to fix failed tests. * Code changes to add global semaphore for concurrency control in address cache. * Code changes to refactor the refresh async method. * Code changes to address review comments. * Code changes to update summary. * [Internal] DocumentClient: Adds TryGetAccountProperties (#4167) * add api * tests * Update test * Rename * Query: Fixes documentation to reflect state of System.Text.Json serializer (#4170) * Update Program.cs * Update Program.cs * Update Program.cs * Update Program.cs --------- Co-authored-by: Matias Quaranta * [Internal] Query: Adds interface for linq serialization functions (#4163) * intial commit * add interface * PR comments and TranslationContext cleanup * update params * fix parameters * PR comments * PR comments * PR comments * simplifying serializer class * interface updates * Update docs * PR comments * PR comments * PR comments - rename and fix assert * Routing: Adds ExcludeRegions Feature to RequestOptions (#4128) * adds excludeRegions * suggested changes * removed unused usings * fixed blank line error * removed using * update contracts * fixed test * reverted automatic changes to BaselineTests * requested changes * bug fix * PPOF test fix * Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview (#4180) * Code changes to enable replica validation for preview. * Code changes to enable replica validation for preview and GA. * VS 17.8 auto runs NuGetAudit and flagging 10.0.2, CosmosDB SDK already mitigated it by changing the MAXDEPATH (#4185) * Documentation: Adds Upsert documentation to include status codes for Created vs Replaced (#4186) * Upset status codes clarification * Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview (#4180) * Code changes to enable replica validation for preview. * Code changes to enable replica validation for preview and GA. --------- Co-authored-by: Debdatta Kunda <87335885+kundadebdatta@users.noreply.github.com> * [Internal] Code Analysis: Fixes all warning in source/test/usage projects (#4188) * [Internal] CodeAnalsis: Fixing CA2200 for test projects * Making code warning clean * fixing the usages projects * Removing the insource overrides * One mroe small fix --------- Co-authored-by: Sourabh Jain * 3.37.0: Adds new SDK versions and contract files (#4191) * Updated change log and bumped up the patch version. * Updated change log and bumped up the minor version. * Updated change log to reflect correct version. * [Internal] Versioning: Adds guidance for versioning SDK releases (#4192) * Create versioning.md * Update versioning.md * Update versioning.md * Update versioning.md * Update README.md * Update versioning.md * Update versioning.md * Apply suggestions from code review Co-authored-by: Kevin Pilch * Update versioning.md * Update versioning.md --------- Co-authored-by: Kevin Pilch * Code changes to sync up with latest master and direct release 3.32.0. --------- Signed-off-by: dependabot[bot] Co-authored-by: Matias Quaranta Co-authored-by: neildsh <35383880+neildsh@users.noreply.github.com> Co-authored-by: Sourabh Jain Co-authored-by: Sourabh Jain Co-authored-by: aavasthy <113193425+aavasthy@users.noreply.github.com> Co-authored-by: Kiran Kumar Kolli Co-authored-by: Aditya Co-authored-by: Fabian Meiswinkel Co-authored-by: akotalwar <94020786+akotalwar@users.noreply.github.com> Co-authored-by: Nalu Tripician Co-authored-by: Nalu Tripician Co-authored-by: Pramod Valavala <43602528+PramodValavala-MSFT@users.noreply.github.com> Co-authored-by: Ezra Haleva <115735172+ezrahaleva-msft@users.noreply.github.com> Co-authored-by: Vivek Ravindran Co-authored-by: Prasad Ullal <36418906+prasadu-microsoft@users.noreply.github.com> Co-authored-by: Philip Thomas <86612891+philipthomas-MSFT@users.noreply.github.com> Co-authored-by: Arthur Augsten Co-authored-by: Augsten Co-authored-by: Ruben Bartelink Co-authored-by: Santosh Kulkarni <66682828+kr-santosh@users.noreply.github.com> Co-authored-by: pravengithub <124255233+pravengithub@users.noreply.github.com> Co-authored-by: DESKTOP-ED57J7H\Prashanth Venkataram Co-authored-by: Justine Cocchi Co-authored-by: Abhijeet Mohanty Co-authored-by: Achint-Agrawal <45819170+Achint-Agrawal@users.noreply.github.com> Co-authored-by: Nimit Shah Co-authored-by: SaurabhSharma-MSFT <38112130+SaurabhSharma-MSFT@users.noreply.github.com> Co-authored-by: leminh98 Co-authored-by: Minh Le Co-authored-by: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> Co-authored-by: Kevin Pilch Co-authored-by: Amaan-Haque <54414760+Amaan-Haque@users.noreply.github.com> Co-authored-by: Amaan Haque Co-authored-by: Amaan Haque Co-authored-by: Baltima <130716409+Baltima@users.noreply.github.com> Co-authored-by: vipulvishal-ms <110802706+vipulvishal-ms@users.noreply.github.com> Co-authored-by: Erik O'Leary <969938+onionhammer@users.noreply.github.com> Co-authored-by: Rinat Minibaev <132935507+rinatmini@users.noreply.github.com> Co-authored-by: Maya-Painter <130110800+Maya-Painter@users.noreply.github.com> Co-authored-by: jiajunpeng-msft <32749342+jiajunpeng-msft@users.noreply.github.com> Co-authored-by: Jiajun Peng Co-authored-by: Heet Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com> Co-authored-by: ernesto1596 Co-authored-by: Mikhail Lipin Co-authored-by: Mikhail Lipin Co-authored-by: David Chaava Co-authored-by: David Chaava Co-authored-by: SrinikhilReddy Co-authored-by: Kevin Pilch Co-authored-by: iain Co-authored-by: Pradeep Chellappan Co-authored-by: Pradeep Chellappan <94089783+pradeep-chellappan@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: sc978345 <115834537+sc978345@users.noreply.github.com> --- CODEOWNERS | 1 + Directory.Build.props | 4 +- ...soft.Azure.Cosmos.Encryption.Custom.csproj | 6 +- .../Tools/Benchmark/BenchmarkConfig.cs | 5 - .../Tools/CTL/CTLConfig.cs | 6 - .../Usage/ApplicationInsights/Program.cs | 2 +- .../Program.cs | 4 +- .../Usage/Encryption/Encryption.csproj | 2 +- .../Usage/ReEncryption/ReEncryption.csproj | 2 +- .../Usage/SystemTextJson/Program.cs | 4 + .../contracts/API_3.37.0-preview.txt | 1611 +++++++++++++++++ .../contracts/API_3.37.0.txt | 1552 ++++++++++++++++ .../src/ClientRetryPolicy.cs | 30 +- .../src/CosmosClientOptions.cs | 12 +- Microsoft.Azure.Cosmos/src/DocumentClient.cs | 17 + .../src/Handler/RequestMessage.cs | 4 +- ...smosElementToSqlScalarExpressionVisitor.cs | 93 + .../src/Linq/DefaultCosmosLinqSerializer.cs | 110 ++ .../src/Linq/ExpressionToSQL.cs | 239 +-- .../src/Linq/ICosmosLinqSerializer.cs | 33 + .../src/Linq/QueryUnderConstruction.cs | 8 +- .../src/Linq/SQLTranslator.cs | 1 - .../src/Linq/TranslationContext.cs | 45 +- Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs | 46 +- .../src/Microsoft.Azure.Cosmos.csproj | 7 +- .../CosmosQueryExecutionContextFactory.cs | 81 +- .../Core/QueryPlan/QueryPartitionProvider.cs | 3 + .../src/Query/v3Query/QueryIterator.cs | 12 +- .../src/RMResources.Designer.cs | 226 ++- Microsoft.Azure.Cosmos/src/RMResources.resx | 70 +- .../src/RequestOptions/RequestOptions.cs | 7 + .../src/Resource/Container/Container.cs | 14 + .../Resource/Container/ContainerCore.Items.cs | 121 +- .../Resource/Container/ContainerInternal.cs | 9 - Microsoft.Azure.Cosmos/src/RetryPolicy.cs | 9 +- .../src/Routing/AsyncCacheNonBlocking.cs | 24 +- .../src/Routing/GatewayAddressCache.cs | 50 +- .../src/Routing/GlobalEndpointManager.cs | 11 +- .../GlobalPartitionEndpointManagerCore.cs | 15 +- .../src/Routing/IGlobalEndpointManager.cs | 2 + .../src/Routing/LocationCache.cs | 103 +- .../src/Util/ConfigurationManager.cs | 32 +- .../src/direct/AuthorizationTokenType.cs | 1 + .../src/direct/BackoffRetryUtility.cs | 115 +- Microsoft.Azure.Cosmos/src/direct/Channel.cs | 8 +- .../src/direct/ClientSideRequestStatistics.cs | 3 +- .../src/direct/ComputedProperty.cs | 85 + .../src/direct/Connection.cs | 38 +- .../src/direct/Constants.cs | 117 +- .../src/direct/CustomTypeExtensions.cs | 2 +- .../src/direct/DataMaskingIncludedPath.cs | 21 + .../src/direct/DataMaskingPolicy.cs | 95 + .../src/direct/Dispatcher.cs | 1 + .../src/direct/DocumentCollection.cs | 83 +- .../src/direct/DocumentServiceRequest.cs | 79 +- .../GoneAndRetryWithRequestRetryPolicy.cs | 49 +- .../src/direct/GoneAndRetryWithRetryPolicy.cs | 3 + .../src/direct/HttpConstants.cs | Bin 115248 -> 117020 bytes .../src/direct/HttpException.cs | 13 +- .../src/direct/HttpTransportClient.cs | 21 + .../direct/IClientSideRequestStatistics.cs | 7 +- .../src/direct/InAccountRestoreParameters.cs | 13 + Microsoft.Azure.Cosmos/src/direct/Int128.cs | 19 + .../src/direct/JSonSerializable.cs | 5 + .../direct/LinuxSystemUtilizationReader.cs | 2 + .../src/direct/LoadBalancingPartition.cs | 13 +- .../src/direct/LocationNames.cs | 36 +- .../src/direct/NotFoundException.cs | 12 +- .../src/direct/OperationType.cs | 7 +- .../src/direct/PartitionKeyInternal.cs | 182 +- .../src/direct/PartitionKeyRange.cs | 13 + Microsoft.Azure.Cosmos/src/direct/Paths.cs | 3 + .../src/direct/PathsHelper.cs | 16 +- .../src/direct/PerfCounters.cs | 45 - .../src/direct/PerformanceActivities.cs | 7 - .../src/direct/PreconditionFailedException.cs | 2 + .../src/direct/RegionProximityUtil.cs | 1081 +++++++---- .../src/direct/RequestNameValueCollection.cs | 578 +++++- .../src/direct/RequestOptions.cs | 10 + .../src/direct/RequestRetryUtility.cs | 129 +- .../src/direct/RntbdConstants.cs | 33 + .../src/direct/ServiceIdentity.cs | 5 + Microsoft.Azure.Cosmos/src/direct/Snapshot.cs | 4 +- .../src/direct/SnapshotContent.cs | 23 + .../src/direct/StatusCodes.cs | 42 +- .../StoreResponseNameValueCollection.cs | 58 + .../src/direct/TimerPool.cs | 1 + .../src/direct/TransportSerialization.cs | 50 +- .../src/direct/TriggerOperation.cs | 7 +- .../src/direct/ValueStopwatch.cs | 6 +- .../src/direct/WFConstants.cs | Bin 25020 -> 26424 bytes .../direct/WindowsSystemUtilizationReader.cs | 2 + .../src/direct/rntbd2/TransportClient.cs | 8 +- .../ClientConfigurationDiagnosticTest.cs | 7 +- .../ClientCreateAndInitializeTest.cs | 4 +- .../ClientTests.cs | 18 + .../CosmosContainerTests.cs | 37 +- .../LinqAttributeContractBaselineTests.cs | 16 +- ...icrosoft.Azure.Cosmos.EmulatorTests.csproj | 1 - .../Query/ConflictsE2ETest.cs | 313 ++++ .../Query/SanityQueryTests.cs | 99 - .../QueryTests.cs | 8 +- .../Utils/TestCommon.cs | 5 +- .../StopwatchAllocationsBenchmark.cs | 4 + .../ClientRetryPolicyTests.cs | 10 +- .../Contracts/ContractEnforcement.cs | 39 +- .../Contracts/ContractEnforcementTests.cs | 10 + .../Contracts/DirectContractTests.cs | 1 - .../Contracts/DotNetSDKAPI.json | 19 + .../Contracts/DotNetSDKTelemetryAPI.json | 356 ++++ .../CosmosBadReplicaTests.cs | 14 +- .../CosmosClientOptionsUnitTests.cs | 149 +- .../CosmosConflictTests.cs | 44 +- .../CosmosHttpClientCoreTests.cs | 11 +- .../GatewayAddressCacheTests.cs | 199 +- .../GatewayStoreModelTest.cs | 2 + .../InterfaceParityTest.cs | 1 + .../LocationCacheTests.cs | 288 ++- .../Microsoft.Azure.Cosmos.Tests.csproj | 3 + .../GlobalPartitionEndpointManagerTests.cs | 76 +- ...GlobalPartitionEndpointManagerUnitTests.cs | 4 +- .../MockSetupsHelper.cs | 11 +- ...misticDirectExecutionQueryBaselineTests.cs | 13 +- .../Query/Pipeline/FullPipelineTests.cs | 249 ++- .../Routing/AsyncCacheNonBlockingTests.cs | 74 +- .../ServicePointAccessorTests.cs | 6 +- README.md | 2 + UpdateContracts.ps1 | 8 + azure-pipelines-official.yml | 22 +- changelog.md | 15 +- docs/PerPartitionAutomaticFailoverDesign.md | 28 + docs/versioning.md | 50 + 132 files changed, 8547 insertions(+), 1455 deletions(-) create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt create mode 100644 Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt create mode 100644 Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs create mode 100644 Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs create mode 100644 Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs create mode 100644 Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs create mode 100644 Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json create mode 100644 docs/PerPartitionAutomaticFailoverDesign.md create mode 100644 docs/versioning.md diff --git a/CODEOWNERS b/CODEOWNERS index 6015906184..d7c4173831 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,4 +20,5 @@ Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts @kirillg @ki Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Contracts @kirillg @kirankumarkolli @ealsur @FabianMeiswinkel Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @Azure/azure-cosmosdb-lt Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetPreviewSDKAPI.json @Azure/azure-cosmosdb-lt +Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json @Azure/azure-cosmosdb-lt CODEOWNERS @kirillg @kirankumarkolli diff --git a/Directory.Build.props b/Directory.Build.props index 514e8e7abb..57ee59de6f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@ - 3.36.0 - 3.36.0 + 3.37.0 + 3.37.0 preview 3.31.5 2.0.3 diff --git a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj index a9f729c9ab..306cd923a9 100644 --- a/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj +++ b/Microsoft.Azure.Cosmos.Encryption.Custom/src/Microsoft.Azure.Cosmos.Encryption.Custom.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 Microsoft.Azure.Cosmos.Encryption.Custom @@ -35,8 +35,8 @@ - - + + diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs index 4b7123eb36..2c523374bf 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/Benchmark/BenchmarkConfig.cs @@ -106,9 +106,6 @@ public class BenchmarkConfig [Option(Required = false, HelpText = "Enable Distributed Tracing")] public bool EnableDistributedTracing { get; set; } = false; - [Option(Required = false, HelpText = "Enable Distributed Tracing")] - public bool EnableDistributedTracing { get; set; } - [Option(Required = false, HelpText = "Client Telemetry Schedule in Seconds")] public int TelemetryScheduleInSec { get; set; } @@ -235,8 +232,6 @@ internal Microsoft.Azure.Cosmos.CosmosClient CreateCosmosClient(string accountKe clientOptions.ConsistencyLevel = (Microsoft.Azure.Cosmos.ConsistencyLevel)Enum.Parse(typeof(Microsoft.Azure.Cosmos.ConsistencyLevel), this.ConsistencyLevel, ignoreCase: true); } - clientOptions.IsDistributedTracingEnabled = this.EnableDistributedTracing; - return new Microsoft.Azure.Cosmos.CosmosClient( this.EndPoint, accountKey, diff --git a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs index 6eb27c52de..8d58271a22 100644 --- a/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs +++ b/Microsoft.Azure.Cosmos.Samples/Tools/CTL/CTLConfig.cs @@ -106,12 +106,6 @@ public string DiagnosticsThresholdDuration [Option("ctl_disable_client_telemetry", Required = false, HelpText = "Disable Client Telemetry Feature in SDK. Make sure you enable it from the portal also.")] public bool DisableClientTelemetry { get; set; } = false; - [Option("ctl_reservoir_type", Required = false, HelpText = "Defines the reservoir type. Valid values are: Uniform, SlidingWindow and ExponentialDecay. The default value is SlidingWindow.")] - public ReservoirTypes ReservoirType { get; set; } = ReservoirTypes.SlidingWindow; - - [Option("ctl_reservoir_sample_size", Required = false, HelpText = "The reservoir sample size.")] - public int ReservoirSampleSize { get; set; } = 1028; - internal TimeSpan RunningTimeDurationAsTimespan { get; private set; } = TimeSpan.FromHours(10); internal TimeSpan DiagnosticsThresholdDurationAsTimespan { get; private set; } = TimeSpan.FromSeconds(60); diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs index 288ce80c64..526452beb2 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ApplicationInsights/Program.cs @@ -16,7 +16,7 @@ internal class Program private static readonly string databaseName = "samples"; private static readonly string containerName = "ai-sample"; - private static TelemetryClient? _telemetryClient; + private static TelemetryClient _telemetryClient; static async Task Main() { diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs index 77580936f7..08d7956f35 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/CustomDiagnosticAndEventListener/Program.cs @@ -83,8 +83,8 @@ public static async Task RunCrudDemo(Container container) internal class Item { [JsonProperty("id")] - public string Id { get; set; } + public string? Id { get; set; } - public string Status { get; set; } + public string? Status { get; set; } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj index 75a2a94922..3d29248400 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/Encryption/Encryption.csproj @@ -8,7 +8,7 @@ latest - + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj index ab88e04988..25d2a6f33e 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj +++ b/Microsoft.Azure.Cosmos.Samples/Usage/ReEncryption/ReEncryption.csproj @@ -8,7 +8,7 @@ latest - + diff --git a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs index ac990a4e28..d66d54f5a2 100644 --- a/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs +++ b/Microsoft.Azure.Cosmos.Samples/Usage/SystemTextJson/Program.cs @@ -177,15 +177,19 @@ private static async Task CleanupAsync() // public class ToDoActivity { + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("id")] public string Id { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("partitionKey")] public string PartitionKey { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("activityId")] public string ActivityId { get; set; } + // Note: System.Text.Json attributes such as JsonPropertyName are currently applied on item CRUD operations and non-LINQ queries, but not on LINQ queries [JsonPropertyName("status")] public string Status { get; set; } } diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt new file mode 100644 index 0000000000..672794b621 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.0-preview.txt @@ -0,0 +1,1611 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public class ChangeFeedItemChange + { + public ChangeFeedItemChange(); + public T Current { get; set; } + public ChangeFeedMetadata Metadata { get; set; } + public T Previous { get; set; } + } + public class ChangeFeedMetadata + { + public ChangeFeedMetadata(DateTime conflictResolutionTimestamp, long lsn, ChangeFeedOperationType operationType, long previousLsn); + public DateTime ConflictResolutionTimestamp { get; } + public bool IsTimeToLiveExpired { get; } + public long Lsn { get; } + public ChangeFeedOperationType OperationType { get; } + public long PreviousLsn { get; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode AllVersionsAndDeletes { get; } + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public enum ChangeFeedOperationType + { + Create = 0, + Delete = 2, + Replace = 1, + } + public sealed class ChangeFeedPolicy + { + public ChangeFeedPolicy(); + public static TimeSpan FullFidelityNoRetention { get; } + public TimeSpan FullFidelityRetention { get; set; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public sealed class ComputedProperty + { + public ComputedProperty(); + public string Name { get; set; } + public string Query { get; set; } + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteAllItemsByPartitionKeyStreamAsync(PartitionKey partitionKey, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> GetPartitionKeyRangesAsync(FeedRange feedRange, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ChangeFeedPolicy ChangeFeedPolicy { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public Collection ComputedProperties { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable BypassIntegratedCache { get; set; } + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public enum PriorityLevel + { + High = 1, + Low = 2, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public bool EnableOptimisticDirectExecution { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public Nullable PriorityLevel { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public class ChangeFeedPolicyDefinition + { + public ContainerBuilder Attach(); + } + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ComputedPropertiesDefinition + { + public T Attach(); + public ComputedPropertiesDefinition WithComputedProperty(string name, string query); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ChangeFeedPolicyDefinition WithChangeFeedPolicy(TimeSpan retention); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public ComputedPropertiesDefinition WithComputedProperties(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query, IDictionary namedParameters); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt b/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt new file mode 100644 index 0000000000..1c02b4efb2 --- /dev/null +++ b/Microsoft.Azure.Cosmos/contracts/API_3.37.0.txt @@ -0,0 +1,1552 @@ +namespace Microsoft.Azure.Cosmos +{ + public class AccountConsistency + { + public AccountConsistency(); + public ConsistencyLevel DefaultConsistencyLevel { get; } + public int MaxStalenessIntervalInSeconds { get; } + public int MaxStalenessPrefix { get; } + } + public class AccountProperties + { + public AccountConsistency Consistency { get; } + public string ETag { get; } + public string Id { get; } + public IEnumerable ReadableRegions { get; } + public IEnumerable WritableRegions { get; } + } + public class AccountRegion + { + public AccountRegion(); + public string Endpoint { get; } + public string Name { get; } + } + public sealed class BoundingBoxProperties + { + public BoundingBoxProperties(); + public double Xmax { get; set; } + public double Xmin { get; set; } + public double Ymax { get; set; } + public double Ymin { get; set; } + } + public abstract class ChangeFeedEstimator + { + protected ChangeFeedEstimator(); + public abstract FeedIterator GetCurrentStateIterator(ChangeFeedEstimatorRequestOptions changeFeedEstimatorRequestOptions=null); + } + public sealed class ChangeFeedEstimatorRequestOptions + { + public ChangeFeedEstimatorRequestOptions(); + public Nullable MaxItemCount { get; set; } + } + public abstract class ChangeFeedMode + { + public static ChangeFeedMode Incremental { get; } + public static ChangeFeedMode LatestVersion { get; } + } + public abstract class ChangeFeedProcessor + { + protected ChangeFeedProcessor(); + public abstract Task StartAsync(); + public abstract Task StopAsync(); + } + public class ChangeFeedProcessorBuilder + { + public ChangeFeedProcessor Build(); + public ChangeFeedProcessorBuilder WithErrorNotification(Container.ChangeFeedMonitorErrorDelegate errorDelegate); + public ChangeFeedProcessorBuilder WithInstanceName(string instanceName); + public ChangeFeedProcessorBuilder WithLeaseAcquireNotification(Container.ChangeFeedMonitorLeaseAcquireDelegate acquireDelegate); + public ChangeFeedProcessorBuilder WithLeaseConfiguration(Nullable acquireInterval=default(Nullable), Nullable expirationInterval=default(Nullable), Nullable renewInterval=default(Nullable)); + public ChangeFeedProcessorBuilder WithLeaseContainer(Container leaseContainer); + public ChangeFeedProcessorBuilder WithLeaseReleaseNotification(Container.ChangeFeedMonitorLeaseReleaseDelegate releaseDelegate); + public ChangeFeedProcessorBuilder WithMaxItems(int maxItemCount); + public ChangeFeedProcessorBuilder WithPollInterval(TimeSpan pollInterval); + public ChangeFeedProcessorBuilder WithStartTime(DateTime startTime); + } + public abstract class ChangeFeedProcessorContext + { + protected ChangeFeedProcessorContext(); + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract Headers Headers { get; } + public abstract string LeaseToken { get; } + } + public sealed class ChangeFeedProcessorState + { + public ChangeFeedProcessorState(string leaseToken, long estimatedLag, string instanceName); + public long EstimatedLag { get; } + public string InstanceName { get; } + public string LeaseToken { get; } + } + public class ChangeFeedProcessorUserException : Exception + { + public ChangeFeedProcessorUserException(Exception originalException, ChangeFeedProcessorContext context); + protected ChangeFeedProcessorUserException(SerializationInfo info, StreamingContext context); + public ChangeFeedProcessorContext ChangeFeedProcessorContext { get; } + public override void GetObjectData(SerializationInfo info, StreamingContext context); + } + public sealed class ChangeFeedRequestOptions : RequestOptions + { + public ChangeFeedRequestOptions(); + public new string IfMatchEtag { get; set; } + public new string IfNoneMatchEtag { get; set; } + public Nullable PageSizeHint { get; set; } + } + public abstract class ChangeFeedStartFrom + { + public static ChangeFeedStartFrom Beginning(); + public static ChangeFeedStartFrom Beginning(FeedRange feedRange); + public static ChangeFeedStartFrom ContinuationToken(string continuationToken); + public static ChangeFeedStartFrom Now(); + public static ChangeFeedStartFrom Now(FeedRange feedRange); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc); + public static ChangeFeedStartFrom Time(DateTime dateTimeUtc, FeedRange feedRange); + } + public sealed class ClientEncryptionIncludedPath + { + public ClientEncryptionIncludedPath(); + public string ClientEncryptionKeyId { get; set; } + public string EncryptionAlgorithm { get; set; } + public string EncryptionType { get; set; } + public string Path { get; set; } + } + public abstract class ClientEncryptionKey + { + protected ClientEncryptionKey(); + public abstract string Id { get; } + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class ClientEncryptionKeyProperties : IEquatable + { + protected ClientEncryptionKeyProperties(); + public ClientEncryptionKeyProperties(string id, string encryptionAlgorithm, byte[] wrappedDataEncryptionKey, EncryptionKeyWrapMetadata encryptionKeyWrapMetadata); + public Nullable CreatedTime { get; } + public string EncryptionAlgorithm { get; } + public EncryptionKeyWrapMetadata EncryptionKeyWrapMetadata { get; } + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public virtual string SelfLink { get; } + public byte[] WrappedDataEncryptionKey { get; } + public bool Equals(ClientEncryptionKeyProperties other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public class ClientEncryptionKeyResponse : Response + { + protected ClientEncryptionKeyResponse(); + public override string ActivityId { get; } + public virtual ClientEncryptionKey ClientEncryptionKey { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ClientEncryptionKeyProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ClientEncryptionKey (ClientEncryptionKeyResponse response); + } + public sealed class ClientEncryptionPolicy + { + public ClientEncryptionPolicy(IEnumerable includedPaths); + public ClientEncryptionPolicy(IEnumerable includedPaths, int policyFormatVersion); + public IEnumerable IncludedPaths { get; } + public int PolicyFormatVersion { get; } + } + public sealed class CompositePath + { + public CompositePath(); + public CompositePathSortOrder Order { get; set; } + public string Path { get; set; } + } + public enum CompositePathSortOrder + { + Ascending = 0, + Descending = 1, + } + public class ConflictProperties + { + public ConflictProperties(); + public string Id { get; } + public OperationKind OperationKind { get; } + public string SelfLink { get; } + } + public enum ConflictResolutionMode + { + Custom = 1, + LastWriterWins = 0, + } + public class ConflictResolutionPolicy + { + public ConflictResolutionPolicy(); + public ConflictResolutionMode Mode { get; set; } + public string ResolutionPath { get; set; } + public string ResolutionProcedure { get; set; } + } + public abstract class Conflicts + { + protected Conflicts(); + public abstract Task DeleteAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetConflictQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetConflictQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract T ReadConflictContent(ConflictProperties conflict); + public abstract Task> ReadCurrentAsync(ConflictProperties conflict, PartitionKey partitionKey, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum ConnectionMode + { + Direct = 1, + Gateway = 0, + } + public enum ConsistencyLevel + { + BoundedStaleness = 1, + ConsistentPrefix = 4, + Eventual = 3, + Session = 2, + Strong = 0, + } + public abstract class Container + { + protected Container(); + public abstract Conflicts Conflicts { get; } + public abstract Database Database { get; } + public abstract string Id { get; } + public abstract Scripts Scripts { get; } + public abstract Task> CreateItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch CreateTransactionalBatch(PartitionKey partitionKey); + public abstract Task DeleteContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> DeleteItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ChangeFeedEstimator GetChangeFeedEstimator(string processorName, Container leaseContainer); + public abstract ChangeFeedProcessorBuilder GetChangeFeedEstimatorBuilder(string processorName, Container.ChangesEstimationHandler estimationDelegate, Nullable estimationPeriod=default(Nullable)); + public abstract FeedIterator GetChangeFeedIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedStreamHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedStreamHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilderWithManualCheckpoint(string processorName, Container.ChangeFeedHandlerWithManualCheckpoint onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangeFeedHandler onChangesDelegate); + public abstract ChangeFeedProcessorBuilder GetChangeFeedProcessorBuilder(string processorName, Container.ChangesHandler onChangesDelegate); + public abstract FeedIterator GetChangeFeedStreamIterator(ChangeFeedStartFrom changeFeedStartFrom, ChangeFeedMode changeFeedMode, ChangeFeedRequestOptions changeFeedRequestOptions=null); + public abstract Task> GetFeedRangesAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract IOrderedQueryable GetItemLinqQueryable(bool allowSynchronousQueryExecution=false, string continuationToken=null, QueryRequestOptions requestOptions=null, CosmosLinqSerializerOptions linqSerializerOptions=null); + public abstract FeedIterator GetItemQueryIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(FeedRange feedRange, QueryDefinition queryDefinition, string continuationToken, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetItemQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task> PatchItemAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task PatchItemStreamAsync(string id, PartitionKey partitionKey, IReadOnlyList patchOperations, PatchItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadContainerStreamAsync(ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadItemAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadItemStreamAsync(string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadManyItemsAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadManyItemsStreamAsync(IReadOnlyList> items, ReadManyRequestOptions readManyRequestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReplaceItemAsync(T item, string id, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceItemStreamAsync(Stream streamPayload, string id, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> UpsertItemAsync(T item, Nullable partitionKey=default(Nullable), ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertItemStreamAsync(Stream streamPayload, PartitionKey partitionKey, ItemRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public delegate Task ChangeFeedHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, IReadOnlyCollection changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangeFeedHandler(ChangeFeedProcessorContext context, IReadOnlyCollection changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedMonitorErrorDelegate(string leaseToken, Exception exception); + public delegate Task ChangeFeedMonitorLeaseAcquireDelegate(string leaseToken); + public delegate Task ChangeFeedMonitorLeaseReleaseDelegate(string leaseToken); + public delegate Task ChangeFeedStreamHandler(ChangeFeedProcessorContext context, Stream changes, CancellationToken cancellationToken); + public delegate Task ChangeFeedStreamHandlerWithManualCheckpoint(ChangeFeedProcessorContext context, Stream changes, Func checkpointAsync, CancellationToken cancellationToken); + public delegate Task ChangesEstimationHandler(long estimatedPendingChanges, CancellationToken cancellationToken); + public delegate Task ChangesHandler(IReadOnlyCollection changes, CancellationToken cancellationToken); + } + public class ContainerProperties + { + public ContainerProperties(); + public ContainerProperties(string id, IReadOnlyList partitionKeyPaths); + public ContainerProperties(string id, string partitionKeyPath); + public Nullable AnalyticalStoreTimeToLiveInSeconds { get; set; } + public ClientEncryptionPolicy ClientEncryptionPolicy { get; set; } + public ConflictResolutionPolicy ConflictResolutionPolicy { get; set; } + public Nullable DefaultTimeToLive { get; set; } + public string ETag { get; } + public GeospatialConfig GeospatialConfig { get; set; } + public string Id { get; set; } + public IndexingPolicy IndexingPolicy { get; set; } + public Nullable LastModified { get; } + public Nullable PartitionKeyDefinitionVersion { get; set; } + public string PartitionKeyPath { get; set; } + public IReadOnlyList PartitionKeyPaths { get; set; } + public string SelfLink { get; } + public string TimeToLivePropertyPath { get; set; } + public UniqueKeyPolicy UniqueKeyPolicy { get; set; } + } + public class ContainerRequestOptions : RequestOptions + { + public ContainerRequestOptions(); + public bool PopulateQuotaInfo { get; set; } + } + public class ContainerResponse : Response + { + protected ContainerResponse(); + public override string ActivityId { get; } + public virtual Container Container { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override ContainerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Container (ContainerResponse response); + } + public class CosmosClient : IDisposable + { + protected CosmosClient(); + public CosmosClient(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, TokenCredential tokenCredential, CosmosClientOptions clientOptions=null); + public CosmosClient(string connectionString, CosmosClientOptions clientOptions=null); + public CosmosClient(string accountEndpoint, string authKeyOrResourceToken, CosmosClientOptions clientOptions=null); + public virtual CosmosClientOptions ClientOptions { get; } + public virtual Uri Endpoint { get; } + public virtual CosmosResponseFactory ResponseFactory { get; } + public static Task CreateAndInitializeAsync(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, TokenCredential tokenCredential, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string connectionString, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public static Task CreateAndInitializeAsync(string accountEndpoint, string authKeyOrResourceToken, IReadOnlyList> containers, CosmosClientOptions cosmosClientOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseIfNotExistsAsync(string id, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public virtual Task CreateDatabaseStreamAsync(DatabaseProperties databaseProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual Container GetContainer(string databaseId, string containerId); + public virtual Database GetDatabase(string id); + public virtual FeedIterator GetDatabaseQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual FeedIterator GetDatabaseQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public virtual Task ReadAccountAsync(); + } + public class CosmosClientOptions + { + public CosmosClientOptions(); + public bool AllowBulkExecution { get; set; } + public string ApplicationName { get; set; } + public IReadOnlyList ApplicationPreferredRegions { get; set; } + public string ApplicationRegion { get; set; } + public ConnectionMode ConnectionMode { get; set; } + public Nullable ConsistencyLevel { get; set; } + public CosmosClientTelemetryOptions CosmosClientTelemetryOptions { get; set; } + public Collection CustomHandlers { get; } + public Nullable EnableContentResponseOnWrite { get; set; } + public bool EnableTcpConnectionEndpointRediscovery { get; set; } + public int GatewayModeMaxConnectionLimit { get; set; } + public Func HttpClientFactory { get; set; } + public Nullable IdleTcpConnectionTimeout { get; set; } + public bool LimitToEndpoint { get; set; } + public Nullable MaxRequestsPerTcpConnection { get; set; } + public Nullable MaxRetryAttemptsOnRateLimitedRequests { get; set; } + public Nullable MaxRetryWaitTimeOnRateLimitedRequests { get; set; } + public Nullable MaxTcpConnectionsPerEndpoint { get; set; } + public Nullable OpenTcpConnectionTimeout { get; set; } + public Nullable PortReuseMode { get; set; } + public TimeSpan RequestTimeout { get; set; } + public CosmosSerializer Serializer { get; set; } + public CosmosSerializationOptions SerializerOptions { get; set; } + public Func ServerCertificateCustomValidationCallback { get; set; } + public Nullable TokenCredentialBackgroundRefreshInterval { get; set; } + public IWebProxy WebProxy { get; set; } + } + public class CosmosClientTelemetryOptions + { + public CosmosClientTelemetryOptions(); + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public bool DisableDistributedTracing { get; set; } + public bool DisableSendingMetricsToService { get; set; } + } + public abstract class CosmosDiagnostics + { + protected CosmosDiagnostics(); + public virtual TimeSpan GetClientElapsedTime(); + public abstract IReadOnlyList> GetContactedRegions(); + public virtual int GetFailedRequestCount(); + public virtual ServerSideCumulativeMetrics GetQueryMetrics(); + public virtual Nullable GetStartTimeUtc(); + public abstract override string ToString(); + } + public class CosmosException : Exception + { + public CosmosException(string message, HttpStatusCode statusCode, int subStatusCode, string activityId, double requestCharge); + public virtual string ActivityId { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual Headers Headers { get; } + public override string Message { get; } + public virtual double RequestCharge { get; } + public virtual string ResponseBody { get; } + public virtual Nullable RetryAfter { get; } + public override string StackTrace { get; } + public virtual HttpStatusCode StatusCode { get; } + public virtual int SubStatusCode { get; } + public override string ToString(); + public virtual bool TryGetHeader(string headerName, out string value); + } + public sealed class CosmosLinqSerializerOptions + { + public CosmosLinqSerializerOptions(); + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public class CosmosOperationCanceledException : OperationCanceledException + { + public CosmosOperationCanceledException(OperationCanceledException originalException, CosmosDiagnostics diagnostics); + protected CosmosOperationCanceledException(SerializationInfo info, StreamingContext context); + public override IDictionary Data { get; } + public CosmosDiagnostics Diagnostics { get; } + public override string HelpLink { get; set; } + public override string Message { get; } + public override string Source { get; set; } + public override string StackTrace { get; } + public override Exception GetBaseException(); + public override void GetObjectData(SerializationInfo info, StreamingContext context); + public override string ToString(); + } + public enum CosmosPropertyNamingPolicy + { + CamelCase = 1, + Default = 0, + } + public abstract class CosmosResponseFactory + { + protected CosmosResponseFactory(); + public abstract FeedResponse CreateItemFeedResponse(ResponseMessage responseMessage); + public abstract ItemResponse CreateItemResponse(ResponseMessage responseMessage); + public abstract StoredProcedureExecuteResponse CreateStoredProcedureExecuteResponse(ResponseMessage responseMessage); + } + public sealed class CosmosSerializationOptions + { + public CosmosSerializationOptions(); + public bool IgnoreNullValues { get; set; } + public bool Indented { get; set; } + public CosmosPropertyNamingPolicy PropertyNamingPolicy { get; set; } + } + public abstract class CosmosSerializer + { + protected CosmosSerializer(); + public abstract T FromStream(Stream stream); + public abstract Stream ToStream(T input); + } + public class CosmosThresholdOptions + { + public CosmosThresholdOptions(); + public TimeSpan NonPointOperationLatencyThreshold { get; set; } + public TimeSpan PointOperationLatencyThreshold { get; set; } + } + public abstract class Database + { + protected Database(); + public abstract CosmosClient Client { get; } + public abstract string Id { get; } + public abstract Task CreateClientEncryptionKeyAsync(ClientEncryptionKeyProperties clientEncryptionKeyProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerIfNotExistsAsync(string id, string partitionKeyPath, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateContainerStreamAsync(ContainerProperties containerProperties, Nullable throughput=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ContainerBuilder DefineContainer(string name, string partitionKeyPath); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract ClientEncryptionKey GetClientEncryptionKey(string id); + public abstract FeedIterator GetClientEncryptionKeyQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Container GetContainer(string id); + public abstract FeedIterator GetContainerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetContainerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract User GetUser(string id); + public abstract FeedIterator GetUserQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadStreamAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadThroughputAsync(RequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ReadThroughputAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(ThroughputProperties throughputProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceThroughputAsync(int throughput, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertUserAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class DatabaseProperties + { + public DatabaseProperties(); + public DatabaseProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class DatabaseResponse : Response + { + protected DatabaseResponse(); + public override string ActivityId { get; } + public virtual Database Database { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override DatabaseProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Database (DatabaseResponse response); + } + public enum DataType + { + LineString = 3, + MultiPolygon = 5, + Number = 0, + Point = 2, + Polygon = 4, + String = 1, + } + public class DedicatedGatewayRequestOptions + { + public DedicatedGatewayRequestOptions(); + public Nullable MaxIntegratedCacheStaleness { get; set; } + } + public class EncryptionKeyWrapMetadata : IEquatable + { + public EncryptionKeyWrapMetadata(EncryptionKeyWrapMetadata source); + public EncryptionKeyWrapMetadata(string type, string name, string value, string algorithm); + public string Algorithm { get; } + public string Name { get; } + public string Type { get; } + public string Value { get; } + public bool Equals(EncryptionKeyWrapMetadata other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class ExcludedPath + { + public ExcludedPath(); + public string Path { get; set; } + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedIterator : IDisposable + { + protected FeedIterator(); + public abstract bool HasMoreResults { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public abstract Task> ReadNextAsync(CancellationToken cancellationToken=default(CancellationToken)); + } + public abstract class FeedRange + { + protected FeedRange(); + public static FeedRange FromJsonString(string toStringValue); + public static FeedRange FromPartitionKey(PartitionKey partitionKey); + public abstract string ToJsonString(); + } + public abstract class FeedResponse : IEnumerable, IEnumerable + { + protected FeedResponse(); + public override string ActivityId { get; } + public abstract string ContinuationToken { get; } + public abstract int Count { get; } + public override string ETag { get; } + public abstract string IndexMetrics { get; } + public override double RequestCharge { get; } + public abstract IEnumerator GetEnumerator(); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public sealed class GeospatialConfig + { + public GeospatialConfig(); + public GeospatialConfig(GeospatialType geospatialType); + public GeospatialType GeospatialType { get; set; } + } + public enum GeospatialType + { + Geography = 0, + Geometry = 1, + } + public class Headers : IEnumerable + { + public Headers(); + public virtual string ActivityId { get; } + public virtual string ContentLength { get; set; } + public virtual string ContentType { get; } + public virtual string ContinuationToken { get; } + public virtual string ETag { get; } + public virtual string this[string headerName] { get; set; } + public virtual string Location { get; } + public virtual double RequestCharge { get; } + public virtual string Session { get; } + public virtual void Add(string headerName, IEnumerable values); + public virtual void Add(string headerName, string value); + public virtual string[] AllKeys(); + public virtual string Get(string headerName); + public virtual IEnumerator GetEnumerator(); + public virtual T GetHeaderValue(string headerName); + public virtual string GetValueOrDefault(string headerName); + public virtual void Remove(string headerName); + public virtual void Set(string headerName, string value); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + public virtual bool TryGetValue(string headerName, out string value); + } + public sealed class IncludedPath + { + public IncludedPath(); + public string Path { get; set; } + } + public enum IndexingDirective + { + Default = 0, + Exclude = 2, + Include = 1, + } + public enum IndexingMode + { + Consistent = 0, + Lazy = 1, + None = 2, + } + public sealed class IndexingPolicy + { + public IndexingPolicy(); + public bool Automatic { get; set; } + public Collection> CompositeIndexes { get; } + public Collection ExcludedPaths { get; } + public Collection IncludedPaths { get; } + public IndexingMode IndexingMode { get; set; } + public Collection SpatialIndexes { get; } + } + public enum IndexKind + { + Hash = 0, + Range = 1, + Spatial = 2, + } + public class ItemRequestOptions : RequestOptions + { + public ItemRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + public IEnumerable PostTriggers { get; set; } + public IEnumerable PreTriggers { get; set; } + public string SessionToken { get; set; } + } + public class ItemResponse : Response + { + protected ItemResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public override HttpStatusCode StatusCode { get; } + } + public enum OperationKind + { + Create = 1, + Delete = 3, + Invalid = 0, + Read = 4, + Replace = 2, + } + public struct PartitionKey : IEquatable + { + public static readonly PartitionKey None; + public static readonly PartitionKey Null; + public static readonly string SystemKeyName; + public static readonly string SystemKeyPath; + public PartitionKey(bool partitionKeyValue); + public PartitionKey(double partitionKeyValue); + public PartitionKey(string partitionKeyValue); + public bool Equals(PartitionKey other); + public override bool Equals(object obj); + public override int GetHashCode(); + public static bool operator ==(PartitionKey left, PartitionKey right); + public static bool operator !=(PartitionKey left, PartitionKey right); + public override string ToString(); + } + public sealed class PartitionKeyBuilder + { + public PartitionKeyBuilder(); + public PartitionKeyBuilder Add(bool val); + public PartitionKeyBuilder Add(double val); + public PartitionKeyBuilder Add(string val); + public PartitionKeyBuilder AddNoneType(); + public PartitionKeyBuilder AddNullValue(); + public PartitionKey Build(); + } + public enum PartitionKeyDefinitionVersion + { + V1 = 1, + V2 = 2, + } + public sealed class PatchItemRequestOptions : ItemRequestOptions + { + public PatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public abstract class PatchOperation + { + protected PatchOperation(); + public virtual string From { get; set; } + public abstract PatchOperationType OperationType { get; } + public abstract string Path { get; } + public static PatchOperation Add(string path, T value); + public static PatchOperation Increment(string path, double value); + public static PatchOperation Increment(string path, long value); + public static PatchOperation Move(string from, string path); + public static PatchOperation Remove(string path); + public static PatchOperation Replace(string path, T value); + public static PatchOperation Set(string path, T value); + public virtual bool TrySerializeValueParameter(CosmosSerializer cosmosSerializer, out Stream valueParam); + } + public enum PatchOperationType + { + Add = 0, + Increment = 4, + Move = 5, + Remove = 1, + Replace = 2, + Set = 3, + } + public abstract class PatchOperation : PatchOperation + { + protected PatchOperation(); + public abstract T Value { get; } + } + public abstract class Permission + { + protected Permission(); + public abstract string Id { get; } + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadAsync(Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public enum PermissionMode : byte + { + All = (byte)2, + Read = (byte)1, + } + public class PermissionProperties + { + public PermissionProperties(string id, PermissionMode permissionMode, Container container, PartitionKey resourcePartitionKey, string itemId); + public PermissionProperties(string id, PermissionMode permissionMode, Container container, Nullable resourcePartitionKey=default(Nullable)); + public string ETag { get; } + public string Id { get; } + public Nullable LastModified { get; } + public PermissionMode PermissionMode { get; } + public Nullable ResourcePartitionKey { get; set; } + public string ResourceUri { get; } + public string SelfLink { get; } + public string Token { get; } + } + public class PermissionResponse : Response + { + protected PermissionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public virtual Permission Permission { get; } + public override double RequestCharge { get; } + public override PermissionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator Permission (PermissionResponse response); + } + public enum PortReuseMode + { + PrivatePortPool = 1, + ReuseUnicastPort = 0, + } + public class QueryDefinition + { + public QueryDefinition(string query); + public string QueryText { get; } + public IReadOnlyList> GetQueryParameters(); + public QueryDefinition WithParameter(string name, object value); + public QueryDefinition WithParameterStream(string name, Stream valueStream); + } + public class QueryRequestOptions : RequestOptions + { + public QueryRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public DedicatedGatewayRequestOptions DedicatedGatewayRequestOptions { get; set; } + public Nullable EnableLowPrecisionOrderBy { get; set; } + public Nullable EnableScanInQuery { get; set; } + public Nullable MaxBufferedItemCount { get; set; } + public Nullable MaxConcurrency { get; set; } + public Nullable MaxItemCount { get; set; } + public Nullable PartitionKey { get; set; } + public Nullable PopulateIndexMetrics { get; set; } + public Nullable ResponseContinuationTokenLimitInKb { get; set; } + public string SessionToken { get; set; } + } + public class ReadManyRequestOptions : RequestOptions + { + public ReadManyRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public static class Regions + { + public const string AustraliaCentral = "Australia Central"; + public const string AustraliaCentral2 = "Australia Central 2"; + public const string AustraliaEast = "Australia East"; + public const string AustraliaSoutheast = "Australia Southeast"; + public const string BrazilSouth = "Brazil South"; + public const string BrazilSoutheast = "Brazil Southeast"; + public const string CanadaCentral = "Canada Central"; + public const string CanadaEast = "Canada East"; + public const string CentralIndia = "Central India"; + public const string CentralUS = "Central US"; + public const string CentralUSEUAP = "Central US EUAP"; + public const string ChinaEast = "China East"; + public const string ChinaEast2 = "China East 2"; + public const string ChinaEast3 = "China East 3"; + public const string ChinaNorth = "China North"; + public const string ChinaNorth2 = "China North 2"; + public const string ChinaNorth3 = "China North 3"; + public const string EastAsia = "East Asia"; + public const string EastUS = "East US"; + public const string EastUS2 = "East US 2"; + public const string EastUS2EUAP = "East US 2 EUAP"; + public const string EastUSSLV = "East US SLV"; + public const string FranceCentral = "France Central"; + public const string FranceSouth = "France South"; + public const string GermanyCentral = "Germany Central"; + public const string GermanyNorth = "Germany North"; + public const string GermanyNortheast = "Germany Northeast"; + public const string GermanyWestCentral = "Germany West Central"; + public const string IsraelCentral = "Israel Central"; + public const string ItalyNorth = "Italy North"; + public const string JapanEast = "Japan East"; + public const string JapanWest = "Japan West"; + public const string JioIndiaCentral = "Jio India Central"; + public const string JioIndiaWest = "Jio India West"; + public const string KoreaCentral = "Korea Central"; + public const string KoreaSouth = "Korea South"; + public const string MalaysiaSouth = "Malaysia South"; + public const string NorthCentralUS = "North Central US"; + public const string NorthEurope = "North Europe"; + public const string NorwayEast = "Norway East"; + public const string NorwayWest = "Norway West"; + public const string PolandCentral = "Poland Central"; + public const string QatarCentral = "Qatar Central"; + public const string SouthAfricaNorth = "South Africa North"; + public const string SouthAfricaWest = "South Africa West"; + public const string SouthCentralUS = "South Central US"; + public const string SoutheastAsia = "Southeast Asia"; + public const string SouthIndia = "South India"; + public const string SwedenCentral = "Sweden Central"; + public const string SwedenSouth = "Sweden South"; + public const string SwitzerlandNorth = "Switzerland North"; + public const string SwitzerlandWest = "Switzerland West"; + public const string UAECentral = "UAE Central"; + public const string UAENorth = "UAE North"; + public const string UKSouth = "UK South"; + public const string UKWest = "UK West"; + public const string USDoDCentral = "USDoD Central"; + public const string USDoDEast = "USDoD East"; + public const string USGovArizona = "USGov Arizona"; + public const string USGovTexas = "USGov Texas"; + public const string USGovVirginia = "USGov Virginia"; + public const string USNatEast = "USNat East"; + public const string USNatWest = "USNat West"; + public const string USSecEast = "USSec East"; + public const string USSecWest = "USSec West"; + public const string WestCentralUS = "West Central US"; + public const string WestEurope = "West Europe"; + public const string WestIndia = "West India"; + public const string WestUS = "West US"; + public const string WestUS2 = "West US 2"; + public const string WestUS3 = "West US 3"; + } + public abstract class RequestHandler + { + protected RequestHandler(); + public RequestHandler InnerHandler { get; set; } + public virtual Task SendAsync(RequestMessage request, CancellationToken cancellationToken); + } + public class RequestMessage : IDisposable + { + public RequestMessage(); + public RequestMessage(HttpMethod method, Uri requestUri); + public virtual Stream Content { get; set; } + public virtual Headers Headers { get; } + public virtual HttpMethod Method { get; } + public virtual Dictionary Properties { get; } + public virtual Uri RequestUri { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + } + public class RequestOptions + { + public RequestOptions(); + public Action AddRequestHeaders { get; set; } + public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + public List ExcludeRegions { get; set; } + public string IfMatchEtag { get; set; } + public string IfNoneMatchEtag { get; set; } + public IReadOnlyDictionary Properties { get; set; } + public RequestOptions ShallowCopy(); + } + public class ResponseMessage : IDisposable + { + public ResponseMessage(); + public ResponseMessage(HttpStatusCode statusCode, RequestMessage requestMessage=null, string errorMessage=null); + public virtual Stream Content { get; set; } + public virtual string ContinuationToken { get; } + public virtual CosmosDiagnostics Diagnostics { get; set; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public string IndexMetrics { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual RequestMessage RequestMessage { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual ResponseMessage EnsureSuccessStatusCode(); + } + public abstract class Response + { + protected Response(); + public abstract string ActivityId { get; } + public abstract CosmosDiagnostics Diagnostics { get; } + public abstract string ETag { get; } + public abstract Headers Headers { get; } + public abstract double RequestCharge { get; } + public abstract T Resource { get; } + public abstract HttpStatusCode StatusCode { get; } + public static implicit operator T (Response response); + } + public abstract class ServerSideCumulativeMetrics + { + protected ServerSideCumulativeMetrics(); + public abstract ServerSideMetrics CumulativeMetrics { get; } + public abstract IReadOnlyList PartitionedMetrics { get; } + } + public abstract class ServerSideMetrics + { + protected ServerSideMetrics(); + public abstract TimeSpan DocumentLoadTime { get; } + public abstract TimeSpan DocumentWriteTime { get; } + public abstract double IndexHitRatio { get; } + public abstract TimeSpan IndexLookupTime { get; } + public abstract long OutputDocumentCount { get; } + public abstract long OutputDocumentSize { get; } + public abstract TimeSpan QueryPreparationTime { get; } + public abstract long RetrievedDocumentCount { get; } + public abstract long RetrievedDocumentSize { get; } + public abstract TimeSpan RuntimeExecutionTime { get; } + public abstract TimeSpan TotalTime { get; } + public abstract TimeSpan VMExecutionTime { get; } + } + public abstract class ServerSidePartitionedMetrics + { + protected ServerSidePartitionedMetrics(); + public abstract string FeedRange { get; } + public abstract Nullable PartitionKeyRangeId { get; } + public abstract ServerSideMetrics ServerSideMetrics { get; } + } + public sealed class SpatialPath + { + public SpatialPath(); + public BoundingBoxProperties BoundingBox { get; set; } + public string Path { get; set; } + public Collection SpatialTypes { get; } + } + public enum SpatialType + { + LineString = 1, + MultiPolygon = 3, + Point = 0, + Polygon = 2, + } + public class ThroughputProperties + { + public Nullable AutoscaleMaxThroughput { get; } + public string ETag { get; } + public Nullable LastModified { get; } + public string SelfLink { get; } + public Nullable Throughput { get; } + public static ThroughputProperties CreateAutoscaleThroughput(int autoscaleMaxThroughput); + public static ThroughputProperties CreateManualThroughput(int throughput); + } + public class ThroughputResponse : Response + { + protected ThroughputResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public Nullable IsReplacePending { get; } + public Nullable MinThroughput { get; } + public override double RequestCharge { get; } + public override ThroughputProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator ThroughputProperties (ThroughputResponse response); + } + public abstract class TransactionalBatch + { + protected TransactionalBatch(); + public abstract TransactionalBatch CreateItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch CreateItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch DeleteItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract Task ExecuteAsync(TransactionalBatchRequestOptions requestOptions, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteAsync(CancellationToken cancellationToken=default(CancellationToken)); + public abstract TransactionalBatch PatchItem(string id, IReadOnlyList patchOperations, TransactionalBatchPatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReadItem(string id, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItemStream(string id, Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch ReplaceItem(string id, T item, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItemStream(Stream streamPayload, TransactionalBatchItemRequestOptions requestOptions=null); + public abstract TransactionalBatch UpsertItem(T item, TransactionalBatchItemRequestOptions requestOptions=null); + } + public class TransactionalBatchItemRequestOptions : RequestOptions + { + public TransactionalBatchItemRequestOptions(); + public Nullable EnableContentResponseOnWrite { get; set; } + public Nullable IndexingDirective { get; set; } + } + public class TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual string ETag { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual Stream ResourceStream { get; } + public virtual TimeSpan RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + } + public class TransactionalBatchOperationResult : TransactionalBatchOperationResult + { + protected TransactionalBatchOperationResult(); + public virtual T Resource { get; set; } + } + public class TransactionalBatchPatchItemRequestOptions : TransactionalBatchItemRequestOptions + { + public TransactionalBatchPatchItemRequestOptions(); + public string FilterPredicate { get; set; } + } + public class TransactionalBatchRequestOptions : RequestOptions + { + public TransactionalBatchRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public string SessionToken { get; set; } + } + public class TransactionalBatchResponse : IDisposable, IEnumerable, IEnumerable, IReadOnlyCollection, IReadOnlyList + { + protected TransactionalBatchResponse(); + public virtual string ActivityId { get; } + public virtual int Count { get; } + public virtual CosmosDiagnostics Diagnostics { get; } + public virtual string ErrorMessage { get; } + public virtual Headers Headers { get; } + public virtual bool IsSuccessStatusCode { get; } + public virtual TransactionalBatchOperationResult this[int index] { get; } + public virtual double RequestCharge { get; } + public virtual Nullable RetryAfter { get; } + public virtual HttpStatusCode StatusCode { get; } + public void Dispose(); + protected virtual void Dispose(bool disposing); + public virtual IEnumerator GetEnumerator(); + public virtual TransactionalBatchOperationResult GetOperationResultAtIndex(int index); + IEnumerator System.Collections.IEnumerable.GetEnumerator(); + } + public class UniqueKey + { + public UniqueKey(); + public Collection Paths { get; } + } + public sealed class UniqueKeyPolicy + { + public UniqueKeyPolicy(); + public Collection UniqueKeys { get; } + } + public abstract class User + { + protected User(); + public abstract string Id { get; } + public abstract Task CreatePermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Permission GetPermission(string id); + public abstract FeedIterator GetPermissionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetPermissionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadAsync(RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceAsync(UserProperties userProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task UpsertPermissionAsync(PermissionProperties permissionProperties, Nullable tokenExpiryInSeconds=default(Nullable), RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class UserProperties + { + protected UserProperties(); + public UserProperties(string id); + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class UserResponse : Response + { + protected UserResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public virtual User User { get; } + public static implicit operator User (UserResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Fluent +{ + public sealed class ClientEncryptionPolicyDefinition + { + public ContainerBuilder Attach(); + public ClientEncryptionPolicyDefinition WithIncludedPath(ClientEncryptionIncludedPath path); + } + public class CompositeIndexDefinition + { + public T Attach(); + public CompositeIndexDefinition Path(string path); + public CompositeIndexDefinition Path(string path, CompositePathSortOrder sortOrder); + } + public class ConflictResolutionDefinition + { + public ContainerBuilder Attach(); + public ConflictResolutionDefinition WithCustomStoredProcedureResolution(string conflictResolutionProcedure); + public ConflictResolutionDefinition WithLastWriterWinsResolution(string conflictResolutionPath); + } + public class ContainerBuilder : ContainerDefinition + { + protected ContainerBuilder(); + public ContainerBuilder(Database database, string name, string partitionKeyPath); + public new ContainerProperties Build(); + public Task CreateAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(ThroughputProperties throughputProperties, CancellationToken cancellationToken=default(CancellationToken)); + public Task CreateIfNotExistsAsync(Nullable throughput=default(Nullable), CancellationToken cancellationToken=default(CancellationToken)); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(); + public ClientEncryptionPolicyDefinition WithClientEncryptionPolicy(int policyFormatVersion); + public ConflictResolutionDefinition WithConflictResolution(); + public UniqueKeyDefinition WithUniqueKey(); + } + public abstract class ContainerDefinition where T : ContainerDefinition + { + public ContainerDefinition(); + public ContainerProperties Build(); + public T WithDefaultTimeToLive(int defaultTtlInSeconds); + public T WithDefaultTimeToLive(TimeSpan defaultTtlTimeSpan); + public IndexingPolicyDefinition WithIndexingPolicy(); + public T WithPartitionKeyDefinitionVersion(PartitionKeyDefinitionVersion partitionKeyDefinitionVersion); + public T WithTimeToLivePropertyPath(string propertyPath); + } + public class CosmosClientBuilder + { + public CosmosClientBuilder(string connectionString); + public CosmosClientBuilder(string accountEndpoint, AzureKeyCredential authKeyOrResourceTokenCredential); + public CosmosClientBuilder(string accountEndpoint, TokenCredential tokenCredential); + public CosmosClientBuilder(string accountEndpoint, string authKeyOrResourceToken); + public CosmosClientBuilder AddCustomHandlers(params RequestHandler[] customHandlers); + public CosmosClient Build(); + public Task BuildAndInitializeAsync(IReadOnlyList> containers, CancellationToken cancellationToken=default(CancellationToken)); + public CosmosClientBuilder WithApplicationName(string applicationName); + public CosmosClientBuilder WithApplicationPreferredRegions(IReadOnlyList applicationPreferredRegions); + public CosmosClientBuilder WithApplicationRegion(string applicationRegion); + public CosmosClientBuilder WithBulkExecution(bool enabled); + public CosmosClientBuilder WithClientTelemetryOptions(CosmosClientTelemetryOptions options); + public CosmosClientBuilder WithConnectionModeDirect(); + public CosmosClientBuilder WithConnectionModeDirect(Nullable idleTcpConnectionTimeout=default(Nullable), Nullable openTcpConnectionTimeout=default(Nullable), Nullable maxRequestsPerTcpConnection=default(Nullable), Nullable maxTcpConnectionsPerEndpoint=default(Nullable), Nullable portReuseMode=default(Nullable), Nullable enableTcpConnectionEndpointRediscovery=default(Nullable)); + public CosmosClientBuilder WithConnectionModeGateway(Nullable maxConnectionLimit=default(Nullable), IWebProxy webProxy=null); + public CosmosClientBuilder WithConsistencyLevel(ConsistencyLevel consistencyLevel); + public CosmosClientBuilder WithContentResponseOnWrite(bool contentResponseOnWrite); + public CosmosClientBuilder WithCustomSerializer(CosmosSerializer cosmosJsonSerializer); + public CosmosClientBuilder WithHttpClientFactory(Func httpClientFactory); + public CosmosClientBuilder WithLimitToEndpoint(bool limitToEndpoint); + public CosmosClientBuilder WithRequestTimeout(TimeSpan requestTimeout); + public CosmosClientBuilder WithSerializerOptions(CosmosSerializationOptions cosmosSerializerOptions); + public CosmosClientBuilder WithThrottlingRetryOptions(TimeSpan maxRetryWaitTimeOnThrottledRequests, int maxRetryAttemptsOnThrottledRequests); + } + public class IndexingPolicyDefinition + { + public IndexingPolicyDefinition(); + public T Attach(); + public IndexingPolicyDefinition WithAutomaticIndexing(bool enabled); + public CompositeIndexDefinition> WithCompositeIndex(); + public PathsDefinition> WithExcludedPaths(); + public PathsDefinition> WithIncludedPaths(); + public IndexingPolicyDefinition WithIndexingMode(IndexingMode indexingMode); + public SpatialIndexDefinition> WithSpatialIndex(); + } + public class PathsDefinition + { + public T Attach(); + public PathsDefinition Path(string path); + } + public class SpatialIndexDefinition + { + public T Attach(); + public SpatialIndexDefinition Path(string path); + public SpatialIndexDefinition Path(string path, params SpatialType[] spatialTypes); + } + public class UniqueKeyDefinition + { + public ContainerBuilder Attach(); + public UniqueKeyDefinition Path(string path); + } +} +namespace Microsoft.Azure.Cosmos.Linq +{ + public static class CosmosLinq + { + public static object InvokeUserDefinedFunction(string udfName, params object[] arguments); + } + public static class CosmosLinqExtensions + { + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> AverageAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> AverageAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> CountAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool IsArray(this object obj); + public static bool IsBool(this object obj); + public static bool IsDefined(this object obj); + public static bool IsNull(this object obj); + public static bool IsNumber(this object obj); + public static bool IsObject(this object obj); + public static bool IsPrimitive(this object obj); + public static bool IsString(this object obj); + public static Task> MaxAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> MinAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static bool RegexMatch(this object obj, string regularExpression); + public static bool RegexMatch(this object obj, string regularExpression, string searchModifier); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task>> SumAsync(this IQueryable> source, CancellationToken cancellationToken=default(CancellationToken)); + public static Task> SumAsync(this IQueryable source, CancellationToken cancellationToken=default(CancellationToken)); + public static FeedIterator ToFeedIterator(this IQueryable query); + public static QueryDefinition ToQueryDefinition(this IQueryable query); + public static FeedIterator ToStreamIterator(this IQueryable query); + } +} +namespace Microsoft.Azure.Cosmos.Scripts +{ + public abstract class Scripts + { + protected Scripts(); + public abstract Task CreateStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task CreateUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task DeleteUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task> ExecuteStoredProcedureAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, PartitionKey partitionKey, dynamic parameters, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ExecuteStoredProcedureStreamAsync(string storedProcedureId, Stream streamPayload, PartitionKey partitionKey, StoredProcedureRequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract FeedIterator GetStoredProcedureQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetStoredProcedureQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetTriggerQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(QueryDefinition queryDefinition, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract FeedIterator GetUserDefinedFunctionQueryStreamIterator(string queryText=null, string continuationToken=null, QueryRequestOptions requestOptions=null); + public abstract Task ReadStoredProcedureAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadTriggerAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReadUserDefinedFunctionAsync(string id, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceStoredProcedureAsync(StoredProcedureProperties storedProcedureProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceTriggerAsync(TriggerProperties triggerProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + public abstract Task ReplaceUserDefinedFunctionAsync(UserDefinedFunctionProperties userDefinedFunctionProperties, RequestOptions requestOptions=null, CancellationToken cancellationToken=default(CancellationToken)); + } + public class StoredProcedureExecuteResponse : Response + { + protected StoredProcedureExecuteResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override T Resource { get; } + public virtual string ScriptLog { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + } + public class StoredProcedureProperties + { + public StoredProcedureProperties(); + public StoredProcedureProperties(string id, string body); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public Nullable LastModified { get; } + public string SelfLink { get; } + } + public class StoredProcedureRequestOptions : RequestOptions + { + public StoredProcedureRequestOptions(); + public Nullable ConsistencyLevel { get; set; } + public bool EnableScriptLogging { get; set; } + public string SessionToken { get; set; } + } + public class StoredProcedureResponse : Response + { + protected StoredProcedureResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override StoredProcedureProperties Resource { get; } + public virtual string SessionToken { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator StoredProcedureProperties (StoredProcedureResponse response); + } + public enum TriggerOperation : short + { + All = (short)0, + Create = (short)1, + Delete = (short)3, + Replace = (short)4, + Update = (short)2, + Upsert = (short)5, + } + public class TriggerProperties + { + public TriggerProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + public TriggerOperation TriggerOperation { get; set; } + public TriggerType TriggerType { get; set; } + } + public class TriggerResponse : Response + { + protected TriggerResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override TriggerProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator TriggerProperties (TriggerResponse response); + } + public enum TriggerType : byte + { + Post = (byte)1, + Pre = (byte)0, + } + public class UserDefinedFunctionProperties + { + public UserDefinedFunctionProperties(); + public string Body { get; set; } + public string ETag { get; } + public string Id { get; set; } + public string SelfLink { get; } + } + public class UserDefinedFunctionResponse : Response + { + protected UserDefinedFunctionResponse(); + public override string ActivityId { get; } + public override CosmosDiagnostics Diagnostics { get; } + public override string ETag { get; } + public override Headers Headers { get; } + public override double RequestCharge { get; } + public override UserDefinedFunctionProperties Resource { get; } + public override HttpStatusCode StatusCode { get; } + public static implicit operator UserDefinedFunctionProperties (UserDefinedFunctionResponse response); + } +} +namespace Microsoft.Azure.Cosmos.Spatial +{ + public sealed class BoundingBox : IEquatable + { + public BoundingBox(Position min, Position max); + public Position Max { get; } + public Position Min { get; } + public bool Equals(BoundingBox other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public abstract class Crs + { + protected Crs(CrsType type); + public static Crs Default { get; } + public CrsType Type { get; } + public static Crs Unspecified { get; } + public static LinkedCrs Linked(string href); + public static LinkedCrs Linked(string href, string type); + public static NamedCrs Named(string name); + } + public enum CrsType + { + Linked = 1, + Named = 0, + Unspecified = 2, + } + public abstract class Geometry + { + protected Geometry(GeometryType type, GeometryParams geometryParams); + public IDictionary AdditionalProperties { get; } + public BoundingBox BoundingBox { get; } + public Crs Crs { get; } + public GeometryType Type { get; } + public double Distance(Geometry to); + public override bool Equals(object obj); + public override int GetHashCode(); + public bool Intersects(Geometry geometry2); + public bool IsValid(); + public GeometryValidationResult IsValidDetailed(); + public bool Within(Geometry outer); + } + public class GeometryParams + { + public GeometryParams(); + public IDictionary AdditionalProperties { get; set; } + public BoundingBox BoundingBox { get; set; } + public Crs Crs { get; set; } + } + public enum GeometryShape + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public enum GeometryType + { + GeometryCollection = 6, + LineString = 2, + MultiLineString = 3, + MultiPoint = 1, + MultiPolygon = 5, + Point = 0, + Polygon = 4, + } + public class GeometryValidationResult + { + public GeometryValidationResult(); + public bool IsValid { get; } + public string Reason { get; } + } + public sealed class LinearRing : IEquatable + { + public LinearRing(IList coordinates); + public ReadOnlyCollection Positions { get; } + public bool Equals(LinearRing other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LineString : Geometry, IEquatable + { + public LineString(IList coordinates); + public LineString(IList coordinates, GeometryParams geometryParams); + public ReadOnlyCollection Positions { get; } + public bool Equals(LineString other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class LinkedCrs : Crs, IEquatable + { + public string Href { get; } + public string HrefType { get; } + public bool Equals(LinkedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class MultiPolygon : Geometry, IEquatable + { + public MultiPolygon(IList polygons); + public MultiPolygon(IList polygons, GeometryParams geometryParams); + public ReadOnlyCollection Polygons { get; } + public bool Equals(MultiPolygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class NamedCrs : Crs, IEquatable + { + public string Name { get; } + public bool Equals(NamedCrs other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Point : Geometry, IEquatable + { + public Point(Position position); + public Point(Position position, GeometryParams geometryParams); + public Point(double longitude, double latitude); + public Position Position { get; } + public bool Equals(Point other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Polygon : Geometry, IEquatable + { + public Polygon(IList rings); + public Polygon(IList rings, GeometryParams geometryParams); + public Polygon(IList externalRingPositions); + public ReadOnlyCollection Rings { get; } + public bool Equals(Polygon other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class PolygonCoordinates : IEquatable + { + public PolygonCoordinates(IList rings); + public ReadOnlyCollection Rings { get; } + public bool Equals(PolygonCoordinates other); + public override bool Equals(object obj); + public override int GetHashCode(); + } + public sealed class Position : IEquatable + { + public Position(IList coordinates); + public Position(double longitude, double latitude); + public Position(double longitude, double latitude, Nullable altitude); + public Nullable Altitude { get; } + public ReadOnlyCollection Coordinates { get; } + public double Latitude { get; } + public double Longitude { get; } + public bool Equals(Position other); + public override bool Equals(object obj); + public override int GetHashCode(); + } +} diff --git a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs index 2933baa1a9..147977e130 100644 --- a/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/ClientRetryPolicy.cs @@ -28,6 +28,7 @@ internal sealed class ClientRetryPolicy : IDocumentClientRetryPolicy private readonly GlobalEndpointManager globalEndpointManager; private readonly GlobalPartitionEndpointManager partitionKeyRangeLocationCache; private readonly bool enableEndpointDiscovery; + private readonly bool isPertitionLevelFailoverEnabled; private int failoverRetryCount; private int sessionTokenRetryCount; @@ -41,8 +42,9 @@ internal sealed class ClientRetryPolicy : IDocumentClientRetryPolicy public ClientRetryPolicy( GlobalEndpointManager globalEndpointManager, GlobalPartitionEndpointManager partitionKeyRangeLocationCache, + RetryOptions retryOptions, bool enableEndpointDiscovery, - RetryOptions retryOptions) + bool isPertitionLevelFailoverEnabled) { this.throttlingRetry = new ResourceThrottleRetryPolicy( retryOptions.MaxRetryAttemptsOnThrottledRequests, @@ -55,6 +57,7 @@ public ClientRetryPolicy( this.sessionTokenRetryCount = 0; this.serviceUnavailableRetryCount = 0; this.canUseMultipleWriteLocations = false; + this.isPertitionLevelFailoverEnabled = isPertitionLevelFailoverEnabled; } /// @@ -243,12 +246,11 @@ private async Task ShouldRetryInternalAsync( if (statusCode == HttpStatusCode.NotFound && subStatusCode == SubStatusCodes.ReadSessionNotAvailable) { - return this.ShouldRetryOnSessionNotAvailable(); + return this.ShouldRetryOnSessionNotAvailable(this.documentServiceRequest); } - + // Received 503 due to client connect timeout or Gateway - if (statusCode == HttpStatusCode.ServiceUnavailable - && ClientRetryPolicy.IsRetriableServiceUnavailable(subStatusCode)) + if (statusCode == HttpStatusCode.ServiceUnavailable) { DefaultTrace.TraceWarning("ClientRetryPolicy: ServiceUnavailable. Refresh cache and retry. Failed Location: {0}; ResourceAddress: {1}", this.documentServiceRequest?.RequestContext?.LocationEndpointToRoute?.ToString() ?? string.Empty, @@ -265,12 +267,6 @@ private async Task ShouldRetryInternalAsync( return null; } - private static bool IsRetriableServiceUnavailable(SubStatusCodes? subStatusCode) - { - return subStatusCode == SubStatusCodes.Unknown || - (subStatusCode.HasValue && subStatusCode.Value.IsSDKGeneratedSubStatus()); - } - private async Task ShouldRetryOnEndpointFailureAsync( bool isReadRequest, bool markBothReadAndWriteAsUnavailable, @@ -334,7 +330,7 @@ private async Task ShouldRetryOnEndpointFailureAsync( return ShouldRetryResult.RetryAfter(retryDelay); } - private ShouldRetryResult ShouldRetryOnSessionNotAvailable() + private ShouldRetryResult ShouldRetryOnSessionNotAvailable(DocumentServiceRequest request) { this.sessionTokenRetryCount++; @@ -347,7 +343,7 @@ private ShouldRetryResult ShouldRetryOnSessionNotAvailable() { if (this.canUseMultipleWriteLocations) { - ReadOnlyCollection endpoints = this.isReadRequest ? this.globalEndpointManager.ReadEndpoints : this.globalEndpointManager.WriteEndpoints; + ReadOnlyCollection endpoints = this.globalEndpointManager.GetApplicableEndpoints(request, this.isReadRequest); if (this.sessionTokenRetryCount > endpoints.Count) { @@ -390,7 +386,7 @@ private ShouldRetryResult ShouldRetryOnSessionNotAvailable() /// /// For a ServiceUnavailable (503.0) we could be having a timeout from Direct/TCP locally or a request to Gateway request with a similar response due to an endpoint not yet available. - /// We try and retry the request only if there are other regions available. + /// We try and retry the request only if there are other regions available. The retry logic is applicable for single master write accounts as well. /// private ShouldRetryResult ShouldRetryOnServiceUnavailable() { @@ -401,9 +397,11 @@ private ShouldRetryResult ShouldRetryOnServiceUnavailable() } if (!this.canUseMultipleWriteLocations - && !this.isReadRequest) + && !this.isReadRequest + && !this.isPertitionLevelFailoverEnabled) { - // Write requests on single master cannot be retried, no other regions available + // Write requests on single master cannot be retried if partition level failover is disabled. + // This means there are no other regions available to serve the writes. return ShouldRetryResult.NoRetry(); } diff --git a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs index 2f648f5272..89c109f877 100644 --- a/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs +++ b/Microsoft.Azure.Cosmos/src/CosmosClientOptions.cs @@ -608,7 +608,7 @@ public Func HttpClientFactory /// /// Enable partition key level failover /// - internal bool EnablePartitionLevelFailover { get; set; } = false; + internal bool EnablePartitionLevelFailover { get; set; } = ConfigurationManager.IsPartitionLevelFailoverEnabled(defaultValue: false); /// /// Quorum Read allowed with eventual consistency account or consistent prefix account. @@ -752,6 +752,7 @@ internal virtual ConnectionPolicy GetConnectionPolicy(int clientId) { this.ValidateDirectTCPSettings(); this.ValidateLimitToEndpointSettings(); + this.ValidatePartitionLevelFailoverSettings(); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -888,6 +889,15 @@ private void ValidateLimitToEndpointSettings() } } + private void ValidatePartitionLevelFailoverSettings() + { + if (this.EnablePartitionLevelFailover + && (this.ApplicationPreferredRegions == null || this.ApplicationPreferredRegions.Count == 0)) + { + throw new ArgumentException($"{nameof(this.ApplicationPreferredRegions)} is required when {nameof(this.EnablePartitionLevelFailover)} is enabled."); + } + } + private void ValidateDirectTCPSettings() { string settingName = string.Empty; diff --git a/Microsoft.Azure.Cosmos/src/DocumentClient.cs b/Microsoft.Azure.Cosmos/src/DocumentClient.cs index 3c261490a7..632c158f96 100644 --- a/Microsoft.Azure.Cosmos/src/DocumentClient.cs +++ b/Microsoft.Azure.Cosmos/src/DocumentClient.cs @@ -1235,6 +1235,23 @@ public virtual Documents.ConsistencyLevel ConsistencyLevel } } + /// + /// Returns the account properties available in the service configuration if the client was initialized. + /// + public bool TryGetCachedAccountProperties(out AccountProperties properties) + { + if (this.isSuccessfullyInitialized + && this.accountServiceConfiguration != null + && this.accountServiceConfiguration.AccountProperties != null) + { + properties = this.accountServiceConfiguration.AccountProperties; + return true; + } + + properties = null; + return false; + } + /// /// Disposes the client for the Azure Cosmos DB service. /// diff --git a/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs b/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs index 6748e79921..67d3dbdc27 100644 --- a/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs +++ b/Microsoft.Azure.Cosmos/src/Handler/RequestMessage.cs @@ -282,7 +282,8 @@ internal DocumentServiceRequest ToDocumentServiceRequest() { this.DocumentServiceRequest.RouteTo(this.PartitionKeyRangeId); } - + + this.DocumentServiceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions; this.OnBeforeRequestHandler(this.DocumentServiceRequest); return this.DocumentServiceRequest; } @@ -299,6 +300,7 @@ private static Headers CreateHeaders() private void OnBeforeRequestHandler(DocumentServiceRequest serviceRequest) { + serviceRequest.RequestContext.ExcludeRegions = this.RequestOptions?.ExcludeRegions; this.OnBeforeSendRequestActions?.Invoke(serviceRequest); } diff --git a/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs b/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs new file mode 100644 index 0000000000..68232330de --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/CosmosElementToSqlScalarExpressionVisitor.cs @@ -0,0 +1,93 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Diagnostics; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.Azure.Cosmos.CosmosElements.Numbers; + using Microsoft.Azure.Cosmos.SqlObjects; + + internal sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor + { + public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); + + private CosmosElementToSqlScalarExpressionVisitor() + { + // Private constructor, since this class is a singleton. + } + + public SqlScalarExpression Visit(CosmosArray cosmosArray) + { + List items = new List(); + foreach (CosmosElement item in cosmosArray) + { + items.Add(item.Accept(this)); + } + + return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosBinary cosmosBinary) + { + // Can not convert binary to scalar expression without knowing the API type. + Debug.Fail("CosmosElementToSqlScalarExpressionVisitor Assert", "Unreachable"); + throw new InvalidOperationException(); + } + + public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) + { + return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); + } + + public SqlScalarExpression Visit(CosmosGuid cosmosGuid) + { + // Can not convert guid to scalar expression without knowing the API type. + Debug.Fail("CosmosElementToSqlScalarExpressionVisitor Assert", "Unreachable"); + throw new InvalidOperationException(); + } + + public SqlScalarExpression Visit(CosmosNull cosmosNull) + { + return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); + } + + public SqlScalarExpression Visit(CosmosNumber cosmosNumber) + { + if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) + { + throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); + } + + return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); + } + + public SqlScalarExpression Visit(CosmosObject cosmosObject) + { + List properties = new List(); + foreach (KeyValuePair prop in cosmosObject) + { + SqlPropertyName name = SqlPropertyName.Create(prop.Key); + CosmosElement value = prop.Value; + SqlScalarExpression expression = value.Accept(this); + SqlObjectProperty property = SqlObjectProperty.Create(name, expression); + properties.Add(property); + } + + return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); + } + + public SqlScalarExpression Visit(CosmosString cosmosString) + { + return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); + } + + public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) + { + return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs new file mode 100644 index 0000000000..024c33fab0 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/DefaultCosmosLinqSerializer.cs @@ -0,0 +1,110 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Diagnostics; + using System.Linq; + using System.Linq.Expressions; + using System.Reflection; + using System.Runtime.Serialization; + using Microsoft.Azure.Documents; + using Newtonsoft.Json; + + internal class DefaultCosmosLinqSerializer : ICosmosLinqSerializer + { + public bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType) + { + // There are two ways to specify a custom attribute + // 1- by specifying the JsonConverterAttribute on a Class/Enum + // [JsonConverter(typeof(StringEnumConverter))] + // Enum MyEnum + // { + // ... + // } + // + // 2- by specifying the JsonConverterAttribute on a property + // class MyClass + // { + // [JsonConverter(typeof(StringEnumConverter))] + // public MyEnum MyEnum; + // } + // + // Newtonsoft gives high precedence to the attribute specified + // on a property over on a type (class/enum) + // so we check both attributes and apply the same precedence rules + // JsonConverterAttribute doesn't allow duplicates so it's safe to + // use FirstOrDefault() + CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + + return memberAttribute != null || typeAttribute != null; + } + + public string Serialize(object value, MemberExpression memberExpression, Type memberType) + { + CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().FirstOrDefault(ca => ca.AttributeType == typeof(Newtonsoft.Json.JsonConverterAttribute)); + CustomAttributeData converterAttribute = memberAttribute ?? typeAttribute; + + Debug.Assert(converterAttribute.ConstructorArguments.Count > 0, $"{nameof(DefaultCosmosLinqSerializer)} Assert!", "At least one constructor argument exists."); + Type converterType = (Type)converterAttribute.ConstructorArguments[0].Value; + + string serializedValue = converterType.GetConstructor(Type.EmptyTypes) != null + ? JsonConvert.SerializeObject(value, (Newtonsoft.Json.JsonConverter)Activator.CreateInstance(converterType)) + : JsonConvert.SerializeObject(value); + + return serializedValue; + } + + public string SerializeScalarExpression(ConstantExpression inputExpression) + { + return JsonConvert.SerializeObject(inputExpression.Value); + } + + public string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) + { + string memberName = null; + + // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. + Newtonsoft.Json.JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); + if (jsonExtensionDataAttribute != null && jsonExtensionDataAttribute.ReadData) + { + return null; + } + + // Json.Net honors JsonPropertyAttribute more than DataMemberAttribute + // So we check for JsonPropertyAttribute first. + JsonPropertyAttribute jsonPropertyAttribute = memberInfo.GetCustomAttribute(true); + if (jsonPropertyAttribute != null && !string.IsNullOrEmpty(jsonPropertyAttribute.PropertyName)) + { + memberName = jsonPropertyAttribute.PropertyName; + } + else + { + DataContractAttribute dataContractAttribute = memberInfo.DeclaringType.GetCustomAttribute(true); + if (dataContractAttribute != null) + { + DataMemberAttribute dataMemberAttribute = memberInfo.GetCustomAttribute(true); + if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name)) + { + memberName = dataMemberAttribute.Name; + } + } + } + + if (memberName == null) + { + memberName = memberInfo.Name; + } + + if (linqSerializerOptions != null) + { + memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName); + } + + return memberName; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs index c64922186f..1b4f91a6a0 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/ExpressionToSQL.cs @@ -14,7 +14,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq.Expressions; using System.Reflection; using Microsoft.Azure.Cosmos.CosmosElements; - using Microsoft.Azure.Cosmos.CosmosElements.Numbers; using Microsoft.Azure.Cosmos.Spatial; using Microsoft.Azure.Cosmos.SqlObjects; using Microsoft.Azure.Documents; @@ -94,7 +93,7 @@ public static SqlQuery TranslateQuery( TranslationContext context = new TranslationContext(linqSerializerOptions, parameters); ExpressionToSql.Translate(inputExpression, context); // ignore result here - QueryUnderConstruction query = context.currentQuery; + QueryUnderConstruction query = context.CurrentQuery; query = query.FlattenAsPossible(); SqlQuery result = query.GetSqlQuery(); @@ -159,7 +158,7 @@ private static Collection TranslateInput(ConstantExpression inputExpression, Tra throw new DocumentQueryException(ClientResources.InputIsNotIDocumentQuery); } - context.currentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); + context.CurrentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); Type elemType = TypeSystem.GetElementType(inputExpression.Type); context.SetInputParameter(elemType, ParameterSubstitution.InputParameterName); // ignore result @@ -169,7 +168,7 @@ private static Collection TranslateInput(ConstantExpression inputExpression, Tra } /// - /// Get a paramter name to be binded to the a collection from the next lambda. + /// Get a parameter name to be binded to the collection from the next lambda. /// It's merely for readability purpose. If that is not possible, use a default /// parameter name. /// @@ -189,7 +188,7 @@ private static string GetBindingParameterName(TranslationContext context) } } - if (parameterName == null) parameterName = ExpressionToSql.DefaultParameterName; + parameterName ??= ExpressionToSql.DefaultParameterName; return parameterName; } @@ -474,17 +473,17 @@ private static SqlScalarExpression VisitBinary(BinaryExpression inputExpression, if (left is SqlMemberIndexerScalarExpression && right is SqlLiteralScalarExpression literalScalarExpression) { - right = ExpressionToSql.ApplyCustomConverters(inputExpression.Left, literalScalarExpression); + right = ExpressionToSql.ApplyCustomConverters(inputExpression.Left, literalScalarExpression, context); } else if (right is SqlMemberIndexerScalarExpression && left is SqlLiteralScalarExpression sqlLiteralScalarExpression) { - left = ExpressionToSql.ApplyCustomConverters(inputExpression.Right, sqlLiteralScalarExpression); + left = ExpressionToSql.ApplyCustomConverters(inputExpression.Right, sqlLiteralScalarExpression, context); } return SqlBinaryScalarExpression.Create(op, left, right); } - private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLiteralScalarExpression right) + private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLiteralScalarExpression right, TranslationContext context) { MemberExpression memberExpression; if (left is UnaryExpression unaryExpression) @@ -504,48 +503,28 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit memberType = memberType.NullableUnderlyingType(); } - // There are two ways to specify a custom attribute - // 1- by specifying the JsonConverterAttribute on a Class/Enum - // [JsonConverter(typeof(StringEnumConverter))] - // Enum MyEnum - // { - // ... - // } - // - // 2- by specifying the JsonConverterAttribute on a property - // class MyClass - // { - // [JsonConverter(typeof(StringEnumConverter))] - // public MyEnum MyEnum; - // } - // - // Newtonsoft gives high precedence to the attribute specified - // on a property over on a type (class/enum) - // so we check both attributes and apply the same precedence rules - // JsonConverterAttribute doesn't allow duplicates so it's safe to - // use FirstOrDefault() - CustomAttributeData memberAttribute = memberExpression.Member.CustomAttributes.Where(ca => ca.AttributeType == typeof(JsonConverterAttribute)).FirstOrDefault(); - CustomAttributeData typeAttribute = memberType.GetsCustomAttributes().Where(ca => ca.AttributeType == typeof(JsonConverterAttribute)).FirstOrDefault(); - - CustomAttributeData converterAttribute = memberAttribute ?? typeAttribute; - if (converterAttribute != null) + bool requiresCustomSerializatior = context.CosmosLinqSerializer.RequiresCustomSerialization(memberExpression, memberType); + if (requiresCustomSerializatior) { - Debug.Assert(converterAttribute.ConstructorArguments.Count > 0); - - Type converterType = (Type)converterAttribute.ConstructorArguments[0].Value; - object value = default(object); // Enum if (memberType.IsEnum()) { - Number64 number64 = ((SqlNumberLiteral)right.Literal).Value; - if (number64.IsDouble) + try { - value = Enum.ToObject(memberType, Number64.ToDouble(number64)); + Number64 number64 = ((SqlNumberLiteral)right.Literal).Value; + if (number64.IsDouble) + { + value = Enum.ToObject(memberType, Number64.ToDouble(number64)); + } + else + { + value = Enum.ToObject(memberType, Number64.ToLong(number64)); + } } - else + catch { - value = Enum.ToObject(memberType, Number64.ToLong(number64)); + value = ((SqlStringLiteral)right.Literal).Value; } } @@ -558,17 +537,7 @@ private static SqlScalarExpression ApplyCustomConverters(Expression left, SqlLit if (value != default(object)) { - string serializedValue; - - if (converterType.GetConstructor(Type.EmptyTypes) != null) - { - serializedValue = JsonConvert.SerializeObject(value, (JsonConverter)Activator.CreateInstance(converterType)); - } - else - { - serializedValue = JsonConvert.SerializeObject(value); - } - + string serializedValue = context.CosmosLinqSerializer.Serialize(value, memberExpression, memberType); return CosmosElement.Parse(serializedValue).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); } } @@ -717,17 +686,17 @@ public static SqlScalarExpression VisitConstant(ConstantExpression inputExpressi if (inputExpression.Type.IsNullable()) { - return ExpressionToSql.VisitConstant(Expression.Constant(inputExpression.Value, Nullable.GetUnderlyingType(inputExpression.Type)), context); + return VisitConstant(Expression.Constant(inputExpression.Value, Nullable.GetUnderlyingType(inputExpression.Type)), context); } - if (context.parameters != null && context.parameters.TryGetValue(inputExpression.Value, out string paramName)) + if (context.Parameters != null && context.Parameters.TryGetValue(inputExpression.Value, out string paramName)) { SqlParameter sqlParameter = SqlParameter.Create(paramName); return SqlParameterRefScalarExpression.Create(sqlParameter); } Type constantType = inputExpression.Value.GetType(); - if (constantType.IsValueType()) + if (constantType.IsValueType) { if (inputExpression.Value is bool boolValue) { @@ -764,13 +733,15 @@ public static SqlScalarExpression VisitConstant(ConstantExpression inputExpressi foreach (object item in enumerable) { - arrayItems.Add(ExpressionToSql.VisitConstant(Expression.Constant(item), context)); + arrayItems.Add(VisitConstant(Expression.Constant(item), context)); } return SqlArrayCreateScalarExpression.Create(arrayItems.ToImmutableArray()); } - return CosmosElement.Parse(JsonConvert.SerializeObject(inputExpression.Value)).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); + string serializedConstant = context.CosmosLinqSerializer.SerializeScalarExpression(inputExpression); + + return CosmosElement.Parse(serializedConstant).Accept(CosmosElementToSqlScalarExpressionVisitor.Singleton); } private static SqlScalarExpression VisitConditional(ConditionalExpression inputExpression, TranslationContext context) @@ -798,7 +769,7 @@ private static SqlScalarExpression VisitParameter(ParameterExpression inputExpre private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpression, TranslationContext context) { SqlScalarExpression memberExpression = ExpressionToSql.VisitScalarExpression(inputExpression.Expression, context); - string memberName = inputExpression.Member.GetMemberName(context.linqSerializerOptions); + string memberName = inputExpression.Member.GetMemberName(context); // If the resulting memberName is null, then the indexer should be on the root of the object. if (memberName == null) @@ -809,7 +780,7 @@ private static SqlScalarExpression VisitMemberAccess(MemberExpression inputExpre // if expression is nullable if (inputExpression.Expression.Type.IsNullable()) { - MemberNames memberNames = context.memberNames; + MemberNames memberNames = context.MemberNames; // ignore .Value if (memberName == memberNames.Value) @@ -853,7 +824,7 @@ private static SqlScalarExpression[] VisitExpressionList(ReadOnlyCollectionThe scalar Any collection private static Collection ConvertToScalarAnyCollection(TranslationContext context) { - SqlQuery query = context.currentQuery.FlattenAsPossible().GetSqlQuery(); + SqlQuery query = context.CurrentQuery.FlattenAsPossible().GetSqlQuery(); SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); Binding binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); - context.currentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); - context.currentQuery.AddBinding(binding); + context.CurrentQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc()); + context.CurrentQuery.AddBinding(binding); SqlSelectSpec selectSpec = SqlSelectValueSpec.Create( SqlBinaryScalarExpression.Create( @@ -1032,7 +1003,7 @@ private static Collection ConvertToScalarAnyCollection(TranslationContext contex SqlPropertyRefScalarExpression.Create(null, SqlIdentifier.Create(parameterExpression.Name))), SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(0)))); SqlSelectClause selectClause = SqlSelectClause.Create(selectSpec); - context.currentQuery.AddSelectClause(selectClause); + context.CurrentQuery.AddSelectClause(selectClause); return new Collection(LinqMethods.Any); } @@ -1173,106 +1144,106 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, context.PushCollection(collection); Collection result = new Collection(inputExpression.Method.Name); - bool shouldBeOnNewQuery = context.currentQuery.ShouldBeOnNewQuery(inputExpression.Method.Name, inputExpression.Arguments.Count); + bool shouldBeOnNewQuery = context.CurrentQuery.ShouldBeOnNewQuery(inputExpression.Method.Name, inputExpression.Arguments.Count); context.PushSubqueryBinding(shouldBeOnNewQuery); switch (inputExpression.Method.Name) { case LinqMethods.Select: { SqlSelectClause select = ExpressionToSql.VisitSelect(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Where: { SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(where, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); break; } case LinqMethods.SelectMany: { - context.currentQuery = context.PackageCurrentQueryIfNeccessary(); + context.CurrentQuery = context.PackageCurrentQueryIfNeccessary(); result = ExpressionToSql.VisitSelectMany(inputExpression.Arguments, context); break; } case LinqMethods.OrderBy: { SqlOrderByClause orderBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); - context.currentQuery = context.currentQuery.AddOrderByClause(orderBy, context); + context.CurrentQuery = context.CurrentQuery.AddOrderByClause(orderBy, context); break; } case LinqMethods.OrderByDescending: { SqlOrderByClause orderBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); - context.currentQuery = context.currentQuery.AddOrderByClause(orderBy, context); + context.CurrentQuery = context.CurrentQuery.AddOrderByClause(orderBy, context); break; } case LinqMethods.ThenBy: { SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, false, context); - context.currentQuery = context.currentQuery.UpdateOrderByClause(thenBy, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } case LinqMethods.ThenByDescending: { SqlOrderByClause thenBy = ExpressionToSql.VisitOrderBy(inputExpression.Arguments, true, context); - context.currentQuery = context.currentQuery.UpdateOrderByClause(thenBy, context); + context.CurrentQuery = context.CurrentQuery.UpdateOrderByClause(thenBy, context); break; } case LinqMethods.Skip: { SqlOffsetSpec offsetSpec = ExpressionToSql.VisitSkip(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddOffsetSpec(offsetSpec, context); + context.CurrentQuery = context.CurrentQuery.AddOffsetSpec(offsetSpec, context); break; } case LinqMethods.Take: { - if (context.currentQuery.HasOffsetSpec()) + if (context.CurrentQuery.HasOffsetSpec()) { SqlLimitSpec limitSpec = ExpressionToSql.VisitTakeLimit(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddLimitSpec(limitSpec, context); + context.CurrentQuery = context.CurrentQuery.AddLimitSpec(limitSpec, context); } else { SqlTopSpec topSpec = ExpressionToSql.VisitTakeTop(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddTopSpec(topSpec); + context.CurrentQuery = context.CurrentQuery.AddTopSpec(topSpec); } break; } case LinqMethods.Distinct: { SqlSelectClause select = ExpressionToSql.VisitDistinct(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Max: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Max); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Min: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Min); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Average: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Avg); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Count: { SqlSelectClause select = ExpressionToSql.VisitCount(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Sum: { SqlSelectClause select = ExpressionToSql.VisitAggregateFunction(inputExpression.Arguments, context, SqlFunctionCallScalarExpression.Names.Sum); - context.currentQuery = context.currentQuery.AddSelectClause(select, context); + context.CurrentQuery = context.CurrentQuery.AddSelectClause(select, context); break; } case LinqMethods.Any: @@ -1282,7 +1253,7 @@ private static Collection VisitMethodCall(MethodCallExpression inputExpression, { // Any is translated to an SELECT VALUE EXISTS() where Any operation itself is treated as a Where. SqlWhereClause where = ExpressionToSql.VisitWhere(inputExpression.Arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(where, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(where, context); } break; } @@ -1509,7 +1480,7 @@ private static SqlScalarExpression VisitScalarExpression(Expression expression, ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); SqlCollection subqueryCollection = ExpressionToSql.CreateSubquerySqlCollection( - query, context, + query, isMinMaxAvgMethod ? SubqueryKind.ArrayScalarExpression : expressionObjKind.Value); Binding newBinding = new Binding(parameterExpression, subqueryCollection, @@ -1536,9 +1507,8 @@ private static SqlScalarExpression VisitScalarExpression(Expression expression, /// Create a subquery SQL collection object for a SQL query /// /// The SQL query object - /// The translation context /// The subquery type - private static SqlCollection CreateSubquerySqlCollection(SqlQuery query, TranslationContext context, SubqueryKind subqueryType) + private static SqlCollection CreateSubquerySqlCollection(SqlQuery query, SubqueryKind subqueryType) { SqlCollection subqueryCollection; switch (subqueryType) @@ -1583,18 +1553,18 @@ private static SqlQuery CreateSubquery(Expression expression, ReadOnlyCollection { bool shouldBeOnNewQuery = context.CurrentSubqueryBinding.ShouldBeOnNewQuery; - QueryUnderConstruction queryBeforeVisit = context.currentQuery; - QueryUnderConstruction packagedQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc(), context.currentQuery); - packagedQuery.fromParameters.SetInputParameter(typeof(object), context.currentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); - context.currentQuery = packagedQuery; + QueryUnderConstruction queryBeforeVisit = context.CurrentQuery; + QueryUnderConstruction packagedQuery = new QueryUnderConstruction(context.GetGenFreshParameterFunc(), context.CurrentQuery); + packagedQuery.fromParameters.SetInputParameter(typeof(object), context.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery).Name, context.InScope); + context.CurrentQuery = packagedQuery; if (shouldBeOnNewQuery) context.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; Collection collection = ExpressionToSql.VisitCollectionExpression(expression, parameters, context); - QueryUnderConstruction subquery = context.currentQuery.GetSubquery(queryBeforeVisit); + QueryUnderConstruction subquery = context.CurrentQuery.GetSubquery(queryBeforeVisit); context.CurrentSubqueryBinding.ShouldBeOnNewQuery = shouldBeOnNewQuery; - context.currentQuery = queryBeforeVisit; + context.CurrentQuery = queryBeforeVisit; SqlQuery sqlSubquery = subquery.FlattenAsPossible().GetSqlQuery(); return sqlSubquery; @@ -1665,7 +1635,7 @@ private static Collection VisitSelectMany(ReadOnlyCollection argumen SqlCollection subqueryCollection = SqlSubqueryCollection.Create(query); ParameterExpression parameterExpression = context.GenFreshParameter(typeof(object), ExpressionToSql.DefaultParameterName); binding = new Binding(parameterExpression, subqueryCollection, isInCollection: false, isInputParameter: true); - context.currentQuery.fromParameters.Add(binding); + context.CurrentQuery.fromParameters.Add(binding); } return collection; @@ -1902,7 +1872,7 @@ private static SqlSelectClause VisitCount( if (arguments.Count == 2) { SqlWhereClause whereClause = ExpressionToSql.VisitWhere(arguments, context); - context.currentQuery = context.currentQuery.AddWhereClause(whereClause, context); + context.CurrentQuery = context.CurrentQuery.AddWhereClause(whereClause, context); } else if (arguments.Count != 1) { @@ -2004,83 +1974,6 @@ private static SqlInputPathCollection ConvertMemberIndexerToPath(SqlMemberIndexe #endregion LINQ Specific Visitors - private sealed class CosmosElementToSqlScalarExpressionVisitor : ICosmosElementVisitor - { - public static readonly CosmosElementToSqlScalarExpressionVisitor Singleton = new CosmosElementToSqlScalarExpressionVisitor(); - - private CosmosElementToSqlScalarExpressionVisitor() - { - // Private constructor, since this class is a singleton. - } - - public SqlScalarExpression Visit(CosmosArray cosmosArray) - { - List items = new List(); - foreach (CosmosElement item in cosmosArray) - { - items.Add(item.Accept(this)); - } - - return SqlArrayCreateScalarExpression.Create(items.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosBinary cosmosBinary) - { - // Can not convert binary to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosBoolean cosmosBoolean) - { - return SqlLiteralScalarExpression.Create(SqlBooleanLiteral.Create(cosmosBoolean.Value)); - } - - public SqlScalarExpression Visit(CosmosGuid cosmosGuid) - { - // Can not convert guid to scalar expression without knowing the API type. - throw new NotImplementedException(); - } - - public SqlScalarExpression Visit(CosmosNull cosmosNull) - { - return SqlLiteralScalarExpression.Create(SqlNullLiteral.Create()); - } - - public SqlScalarExpression Visit(CosmosNumber cosmosNumber) - { - if (!(cosmosNumber is CosmosNumber64 cosmosNumber64)) - { - throw new ArgumentException($"Unknown {nameof(CosmosNumber)} type: {cosmosNumber.GetType()}."); - } - - return SqlLiteralScalarExpression.Create(SqlNumberLiteral.Create(cosmosNumber64.GetValue())); - } - - public SqlScalarExpression Visit(CosmosObject cosmosObject) - { - List properties = new List(); - foreach (KeyValuePair prop in cosmosObject) - { - SqlPropertyName name = SqlPropertyName.Create(prop.Key); - CosmosElement value = prop.Value; - SqlScalarExpression expression = value.Accept(this); - SqlObjectProperty property = SqlObjectProperty.Create(name, expression); - properties.Add(property); - } - - return SqlObjectCreateScalarExpression.Create(properties.ToImmutableArray()); - } - - public SqlScalarExpression Visit(CosmosString cosmosString) - { - return SqlLiteralScalarExpression.Create(SqlStringLiteral.Create(cosmosString.Value)); - } - - public SqlScalarExpression Visit(CosmosUndefined cosmosUndefined) - { - return SqlLiteralScalarExpression.Create(SqlUndefinedLiteral.Create()); - } - } private enum SubqueryKind { ArrayScalarExpression, diff --git a/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs new file mode 100644 index 0000000000..f31490832d --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/Linq/ICosmosLinqSerializer.cs @@ -0,0 +1,33 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ +namespace Microsoft.Azure.Cosmos.Linq +{ + using System; + using System.Linq.Expressions; + using System.Reflection; + + internal interface ICosmosLinqSerializer + { + /// + /// Returns true if there are custom attributes on a member expression. + /// + bool RequiresCustomSerialization(MemberExpression memberExpression, Type memberType); + + // TODO : Clean up this interface member for better generalizability + /// + /// Serializes object. + /// + string Serialize(object value, MemberExpression memberExpression, Type memberType); + + /// + /// Serializes a ConstantExpression. + /// + string SerializeScalarExpression(ConstantExpression inputExpression); + + /// + /// Serializes a member name with LINQ serializer options applied. + /// + string SerializeMemberName(MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null); + } +} diff --git a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs index c5c0573a14..d2e19046e1 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/QueryUnderConstruction.cs @@ -583,13 +583,13 @@ public QueryUnderConstruction AddOrderByClause(SqlOrderByClause orderBy, Transla public QueryUnderConstruction UpdateOrderByClause(SqlOrderByClause thenBy, TranslationContext context) { - List items = new List(context.currentQuery.orderByClause.OrderByItems); + List items = new List(context.CurrentQuery.orderByClause.OrderByItems); items.AddRange(thenBy.OrderByItems); - context.currentQuery.orderByClause = SqlOrderByClause.Create(items.ToImmutableArray()); + context.CurrentQuery.orderByClause = SqlOrderByClause.Create(items.ToImmutableArray()); - foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) context.currentQuery.AddBinding(binding); + foreach (Binding binding in context.CurrentSubqueryBinding.TakeBindings()) context.CurrentQuery.AddBinding(binding); - return context.currentQuery; + return context.CurrentQuery; } public QueryUnderConstruction AddOffsetSpec(SqlOffsetSpec offsetSpec, TranslationContext context) diff --git a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs index 8648019219..c0bd6d38a0 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/SQLTranslator.cs @@ -6,7 +6,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Collections.Generic; using System.Linq.Expressions; using Microsoft.Azure.Cosmos.Query.Core; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; /// diff --git a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs index 8fc95d8701..f5d53bd1e7 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TranslationContext.cs @@ -7,7 +7,6 @@ namespace Microsoft.Azure.Cosmos.Linq using System; using System.Collections.Generic; using System.Linq.Expressions; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Cosmos.SqlObjects; using static Microsoft.Azure.Cosmos.Linq.ExpressionToSql; using static Microsoft.Azure.Cosmos.Linq.FromParameterBindings; @@ -20,39 +19,54 @@ internal sealed class TranslationContext /// /// Member names for special mapping cases /// - internal readonly MemberNames memberNames; + public readonly MemberNames MemberNames; + + /// + /// The LINQ serializer + /// + public readonly ICosmosLinqSerializer CosmosLinqSerializer; + + /// + /// User-provided LINQ serializer options + /// + public CosmosLinqSerializerOptions LinqSerializerOptions; /// /// Set of parameters in scope at any point; used to generate fresh parameter names if necessary. /// public HashSet InScope; + /// /// Query that is being assembled. /// - public QueryUnderConstruction currentQuery; + public QueryUnderConstruction CurrentQuery; /// /// Dictionary for parameter name and value /// - public IDictionary parameters; + public IDictionary Parameters; /// /// If the FROM clause uses a parameter name, it will be substituted for the parameter used in /// the lambda expressions for the WHERE and SELECT clauses. /// private ParameterSubstitution substitutions; + /// /// We are currently visiting these methods. /// private List methodStack; + /// /// Stack of parameters from lambdas currently in scope. /// private List lambdaParametersStack; + /// /// Stack of collection-valued inputs. /// private List collectionStack; + /// /// The stack of subquery binding information. /// @@ -65,15 +79,14 @@ public TranslationContext(CosmosLinqSerializerOptions linqSerializerOptions, IDi this.methodStack = new List(); this.lambdaParametersStack = new List(); this.collectionStack = new List(); - this.currentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); + this.CurrentQuery = new QueryUnderConstruction(this.GetGenFreshParameterFunc()); this.subqueryBindingStack = new Stack(); - this.linqSerializerOptions = linqSerializerOptions; - this.parameters = parameters; - this.memberNames = new MemberNames(linqSerializerOptions); + this.LinqSerializerOptions = linqSerializerOptions; + this.Parameters = parameters; + this.MemberNames = new MemberNames(linqSerializerOptions); + this.CosmosLinqSerializer = new DefaultCosmosLinqSerializer(); } - public CosmosLinqSerializerOptions linqSerializerOptions; - public Expression LookupSubstitution(ParameterExpression parameter) { return this.substitutions.Lookup(parameter); @@ -103,12 +116,12 @@ public void PushParameter(ParameterExpression parameter, bool shouldBeOnNewQuery if (last.isOuter) { // substitute - ParameterExpression inputParam = this.currentQuery.GetInputParameterInContext(shouldBeOnNewQuery); + ParameterExpression inputParam = this.CurrentQuery.GetInputParameterInContext(shouldBeOnNewQuery); this.substitutions.AddSubstitution(parameter, inputParam); } else { - this.currentQuery.Bind(parameter, last.inner); + this.CurrentQuery.Bind(parameter, last.inner); } } @@ -182,7 +195,7 @@ public void PopCollection() /// Suggested name for the input parameter. public ParameterExpression SetInputParameter(Type type, string name) { - return this.currentQuery.fromParameters.SetInputParameter(type, name, this.InScope); + return this.CurrentQuery.fromParameters.SetInputParameter(type, name, this.InScope); } /// @@ -193,7 +206,7 @@ public ParameterExpression SetInputParameter(Type type, string name) public void SetFromParameter(ParameterExpression parameter, SqlCollection collection) { Binding binding = new Binding(parameter, collection, isInCollection: true); - this.currentQuery.fromParameters.Add(binding); + this.CurrentQuery.fromParameters.Add(binding); } /// @@ -258,11 +271,11 @@ public QueryUnderConstruction PackageCurrentQueryIfNeccessary() { if (this.CurrentSubqueryBinding.ShouldBeOnNewQuery) { - this.currentQuery = this.currentQuery.PackageQuery(this.InScope); + this.CurrentQuery = this.CurrentQuery.PackageQuery(this.InScope); this.CurrentSubqueryBinding.ShouldBeOnNewQuery = false; } - return this.currentQuery; + return this.CurrentQuery; } public class SubqueryBinding diff --git a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs index 7c8e62d69c..e11c145c71 100644 --- a/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs +++ b/Microsoft.Azure.Cosmos/src/Linq/TypeSystem.cs @@ -10,10 +10,7 @@ namespace Microsoft.Azure.Cosmos.Linq using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; - using System.Runtime.Serialization; - using Microsoft.Azure.Cosmos.Serializer; using Microsoft.Azure.Documents; - using Newtonsoft.Json; internal static class TypeSystem { @@ -22,48 +19,9 @@ public static Type GetElementType(Type type) return GetElementType(type, new HashSet()); } - public static string GetMemberName(this MemberInfo memberInfo, CosmosLinqSerializerOptions linqSerializerOptions = null) + public static string GetMemberName(this MemberInfo memberInfo, TranslationContext context) { - string memberName = null; - - // Check if Newtonsoft JsonExtensionDataAttribute is present on the member, if so, return empty member name. - JsonExtensionDataAttribute jsonExtensionDataAttribute = memberInfo.GetCustomAttribute(true); - if (jsonExtensionDataAttribute != null && jsonExtensionDataAttribute.ReadData) - { - return null; - } - - // Json.Net honors JsonPropertyAttribute more than DataMemberAttribute - // So we check for JsonPropertyAttribute first. - JsonPropertyAttribute jsonPropertyAttribute = memberInfo.GetCustomAttribute(true); - if (jsonPropertyAttribute != null && !string.IsNullOrEmpty(jsonPropertyAttribute.PropertyName)) - { - memberName = jsonPropertyAttribute.PropertyName; - } - else - { - DataContractAttribute dataContractAttribute = memberInfo.DeclaringType.GetCustomAttribute(true); - if (dataContractAttribute != null) - { - DataMemberAttribute dataMemberAttribute = memberInfo.GetCustomAttribute(true); - if (dataMemberAttribute != null && !string.IsNullOrEmpty(dataMemberAttribute.Name)) - { - memberName = dataMemberAttribute.Name; - } - } - } - - if (memberName == null) - { - memberName = memberInfo.Name; - } - - if (linqSerializerOptions != null) - { - memberName = CosmosSerializationUtil.GetStringWithPropertyNamingPolicy(linqSerializerOptions, memberName); - } - - return memberName; + return context.CosmosLinqSerializer.SerializeMemberName(memberInfo, context.LinqSerializerOptions); } private static Type GetElementType(Type type, HashSet visitedSet) diff --git a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj index 5a16c54a99..5e7b157bbe 100644 --- a/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj +++ b/Microsoft.Azure.Cosmos/src/Microsoft.Azure.Cosmos.csproj @@ -43,11 +43,11 @@ true $(LangVersion) LICENSE - CS1572; CS1573; CS1574; CS1580 + CS1572; CS1573; CS1574; CS1580; CS1570; CS0472 - + @@ -118,8 +118,7 @@ - - + diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs index adb19c303f..08e6292a03 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/Pipeline/CosmosQueryExecutionContextFactory.cs @@ -161,29 +161,7 @@ private static async Task> TryCreateCoreContextAsy } PartitionedQueryExecutionInfo partitionedQueryExecutionInfo; - if (inputParameters.ForcePassthrough) - { - partitionedQueryExecutionInfo = new PartitionedQueryExecutionInfo() - { - QueryInfo = new QueryInfo() - { - Aggregates = null, - DistinctType = DistinctQueryType.None, - GroupByAliases = null, - GroupByAliasToAggregateType = null, - GroupByExpressions = null, - HasSelectValue = false, - Limit = null, - Offset = null, - OrderBy = null, - OrderByExpressions = null, - RewrittenQuery = null, - Top = null, - }, - QueryRanges = new List>(), - }; - } - else if (queryPlanFromContinuationToken != null) + if (queryPlanFromContinuationToken != null) { partitionedQueryExecutionInfo = queryPlanFromContinuationToken; } @@ -270,26 +248,7 @@ private static async Task> TryCreateFromPartitione inputParameters.InitialFeedRange, trace); - bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue - || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) - && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); - bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates - && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct - && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; - bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; - - bool clientStreamingQuery = - serverStreamingQuery - && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy - && !partitionedQueryExecutionInfo.QueryInfo.HasTop - && !partitionedQueryExecutionInfo.QueryInfo.HasLimit - && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; - bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; - - bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; - TryCatch tryCreatePipelineStage; - Documents.PartitionKeyRange targetRange = await TryGetTargetRangeOptimisticDirectExecutionAsync( inputParameters, partitionedQueryExecutionInfo, @@ -311,6 +270,22 @@ private static async Task> TryCreateFromPartitione } else { + bool singleLogicalPartitionKeyQuery = inputParameters.PartitionKey.HasValue + || ((partitionedQueryExecutionInfo.QueryRanges.Count == 1) + && partitionedQueryExecutionInfo.QueryRanges[0].IsSingleValue); + bool serverStreamingQuery = !partitionedQueryExecutionInfo.QueryInfo.HasAggregates + && !partitionedQueryExecutionInfo.QueryInfo.HasDistinct + && !partitionedQueryExecutionInfo.QueryInfo.HasGroupBy; + bool streamingSinglePartitionQuery = singleLogicalPartitionKeyQuery && serverStreamingQuery; + + bool clientStreamingQuery = serverStreamingQuery + && !partitionedQueryExecutionInfo.QueryInfo.HasOrderBy + && !partitionedQueryExecutionInfo.QueryInfo.HasTop + && !partitionedQueryExecutionInfo.QueryInfo.HasLimit + && !partitionedQueryExecutionInfo.QueryInfo.HasOffset; + bool streamingCrossContinuationQuery = !singleLogicalPartitionKeyQuery && clientStreamingQuery; + bool createPassthroughQuery = streamingSinglePartitionQuery || streamingCrossContinuationQuery; + if (createPassthroughQuery) { SetTestInjectionPipelineType(inputParameters, Passthrough); @@ -432,7 +407,6 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx inputParameters.PartitionedQueryExecutionInfo, inputParameters.ExecutionEnvironment, inputParameters.ReturnResultsInDeterministicOrder, - inputParameters.ForcePassthrough, inputParameters.EnableOptimisticDirectExecution, inputParameters.TestInjections); } @@ -551,7 +525,20 @@ private static TryCatch TryCreateSpecializedDocumentQueryEx if (queryInfo.HasOrderBy) { int top; - if (queryInfo.HasTop && (top = partitionedQueryExecutionInfo.QueryInfo.Top.Value) > 0) + if (queryInfo.HasTop && (partitionedQueryExecutionInfo.QueryInfo.Top.Value > 0)) + { + top = partitionedQueryExecutionInfo.QueryInfo.Top.Value; + } + else if (queryInfo.HasLimit && (partitionedQueryExecutionInfo.QueryInfo.Limit.Value > 0)) + { + top = (partitionedQueryExecutionInfo.QueryInfo.Offset ?? 0) + partitionedQueryExecutionInfo.QueryInfo.Limit.Value; + } + else + { + top = 0; + } + + if (top > 0) { // All partitions should initially fetch about 1/nth of the top value. long pageSizeWithTop = (long)Math.Min( @@ -733,7 +720,7 @@ private static void SetTestInjectionPipelineType(InputParameters inputParameters { responseStats.PipelineType = TestInjections.PipelineType.Specialized; } - else + else { responseStats.PipelineType = TestInjections.PipelineType.Passthrough; } @@ -852,7 +839,6 @@ public InputParameters( PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, ExecutionEnvironment? executionEnvironment, bool? returnResultsInDeterministicOrder, - bool forcePassthrough, bool enableOptimisticDirectExecution, TestInjections testInjections) { @@ -886,7 +872,6 @@ public InputParameters( this.PartitionedQueryExecutionInfo = partitionedQueryExecutionInfo; this.ExecutionEnvironment = executionEnvironment.GetValueOrDefault(InputParameters.DefaultExecutionEnvironment); this.ReturnResultsInDeterministicOrder = returnResultsInDeterministicOrder.GetValueOrDefault(InputParameters.DefaultReturnResultsInDeterministicOrder); - this.ForcePassthrough = forcePassthrough; this.EnableOptimisticDirectExecution = enableOptimisticDirectExecution; this.TestInjections = testInjections; } @@ -903,7 +888,6 @@ public InputParameters( public ExecutionEnvironment ExecutionEnvironment { get; } public bool ReturnResultsInDeterministicOrder { get; } public TestInjections TestInjections { get; } - public bool ForcePassthrough { get; } public bool EnableOptimisticDirectExecution { get; } public InputParameters WithContinuationToken(CosmosElement token) @@ -920,7 +904,6 @@ public InputParameters WithContinuationToken(CosmosElement token) this.PartitionedQueryExecutionInfo, this.ExecutionEnvironment, this.ReturnResultsInDeterministicOrder, - this.ForcePassthrough, this.EnableOptimisticDirectExecution, this.TestInjections); } diff --git a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs index c62a65b27a..6f95673d80 100644 --- a/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs +++ b/Microsoft.Azure.Cosmos/src/Query/Core/QueryPlan/QueryPartitionProvider.cs @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query.Core.QueryPlan { using System; using System.Collections.Generic; + using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -290,6 +291,8 @@ internal TryCatch TryGetPartitionedQueryE MaxDepth = 64, // https://github.com/advisories/GHSA-5crp-9r3c-p9vr }); + Debug.Assert(!(queryInfoInternal.QueryInfo.HasTop && queryInfoInternal.QueryInfo.HasLimit)); + return TryCatch.FromResult(queryInfoInternal); } diff --git a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs index 7dfcea9818..344e3e56e4 100644 --- a/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs +++ b/Microsoft.Azure.Cosmos/src/Query/v3Query/QueryIterator.cs @@ -6,7 +6,7 @@ namespace Microsoft.Azure.Cosmos.Query { using System; using System.Collections.Generic; - using System.Linq; + using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.CosmosElements; @@ -66,8 +66,8 @@ public static QueryIterator Create( string resourceLink, bool isContinuationExpected, bool allowNonValueAggregateQuery, - bool forcePassthrough, - PartitionedQueryExecutionInfo partitionedQueryExecutionInfo) + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo, + Documents.ResourceType resourceType) { if (queryRequestOptions == null) { @@ -77,7 +77,7 @@ public static QueryIterator Create( Guid correlatedActivityId = Guid.NewGuid(); CosmosQueryContextCore cosmosQueryContext = new CosmosQueryContextCore( client: client, - resourceTypeEnum: Documents.ResourceType.Document, + resourceTypeEnum: resourceType, operationType: Documents.OperationType.Query, resourceType: typeof(QueryResponseCore), resourceLink: resourceLink, @@ -90,7 +90,8 @@ public static QueryIterator Create( containerCore, client, correlatedActivityId, - queryRequestOptions); + queryRequestOptions, + resourceType: resourceType); DocumentContainer documentContainer = new DocumentContainer(networkAttachedDocumentContainer); CosmosElement requestContinuationToken; @@ -143,7 +144,6 @@ public static QueryIterator Create( partitionedQueryExecutionInfo: partitionedQueryExecutionInfo, executionEnvironment: queryRequestOptions.ExecutionEnvironment, returnResultsInDeterministicOrder: queryRequestOptions.ReturnResultsInDeterministicOrder, - forcePassthrough: forcePassthrough, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); diff --git a/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs b/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs index 18f3aa1cdb..9dfc7537eb 100644 --- a/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs +++ b/Microsoft.Azure.Cosmos/src/RMResources.Designer.cs @@ -766,6 +766,28 @@ internal static string EnableMultipleWriteLocationsAndEnableServerlessNotSupport } } + /// + /// Looks up a localized string similar to Cannot set EnableMultipleWriteLocations on an account with EnableTieredStorageV1. + /// + internal static string EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported + { + get + { + return ResourceManager.GetString("EnableMultipleWriteLocationsAndEnableTieredStorageV1NotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableOnlyColdStorageContainersInAccountV1 on an account with EnableMaterializedViews + /// + internal static string EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported + { + get + { + return ResourceManager.GetString("EnableOnlyColdStorageContainersInAccountV1AndEnableMaterializedViewsNotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to Accounts configured with default consistency level as 'Strong' cannot be enabled for multiple write locations(i.e. EnableMultipleWriteLocations=true). Consider relaxing default consistency level of the account to enable multiple write locations.. /// @@ -1123,6 +1145,17 @@ internal static string GlobalAndWriteRegionMisMatch } } + /// + /// Looks up a localized string similar to Federation and region are not matching. + /// + internal static string FederationAndRegionMismatch + { + get + { + return ResourceManager.GetString("FederationAndRegionMismatch", resourceCulture); + } + } + /// /// Looks up a localized string similar to Global Strong write barrier has not been met for the request.. /// @@ -1389,13 +1422,24 @@ internal static string InvalidFailoverPriority /// - /// Looks up a localized string similar to Federation cap action is not currently supported. + /// Looks up a localized string similar to The CapUncapMetadata action '{0}' is not currently supported.. /// - internal static string InvalidFederationCapAction + internal static string InvalidFederationCapUncapMetadataAction { get { - return ResourceManager.GetString("InvalidFederationCapAction", resourceCulture); + return ResourceManager.GetString("InvalidFederationCapUncapMetadataAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The CapUncapMetadata source '{0}' is invalid.. + /// + internal static string InvalidFederationCapUncapMetadataSource + { + get + { + return ResourceManager.GetString("InvalidFederationCapUncapMetadataSource", resourceCulture); } } @@ -3232,6 +3276,17 @@ internal static string ServiceUnavailable } } + /// + /// Looks up a localized string similar to Service Unavailable due to high demand in the region. + /// + internal static string ServiceUnavailableDueToHighDemandInRegion + { + get + { + return ResourceManager.GetString("ServiceUnavailableDueToHighDemandInRegion", resourceCulture); + } + } + /// /// Looks up a localized string similar to Could not find service hosting DocumentCollection with ResourceId {0}. /// @@ -3376,13 +3431,13 @@ internal static string SystemDatabaseAccountPitrEnabledNotSupported } /// - /// Looks up a localized string similar to Continuous backup, synapse link, full fidelity change feed and materialized views are currently not supported with cross tenant customer-managed keys features. + /// Looks up a localized string similar to Cross tenant CMK database account doesn't support using delegated identity as the default identity. /// - internal static string CrossTenantCMKDatabaseAccountLogstoreFeaturesNotSupported + internal static string CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported { get { - return ResourceManager.GetString("CrossTenantCMKDatabaseAccountLogstoreFeaturesNotSupported", resourceCulture); + return ResourceManager.GetString("CrossTenantCMKDatabaseAccountDelegatedIdentityNotSupported", resourceCulture); } } @@ -4146,6 +4201,17 @@ internal static string UpsertsForScriptsWithMultiplePartitionsAreNotSupported } } + /// + /// Looks up a localized string similar to Web socket requests are not supported. + /// + internal static string WebSocketRequestsNotSupported + { + get + { + return ResourceManager.GetString("WebSocketRequestsNotSupported", resourceCulture); + } + } + /// /// Looks up a localized string similar to Cannot offline write region when automatic failover is not enabled. /// @@ -4269,12 +4335,9 @@ internal static string FreeTierNotSupportedForInternalSubscription } } - -#pragma warning disable CS1570 // XML comment has badly formed XML -/// Looks up a localized string similar to Could not resolve DataTransfer state store account for region [{0}].. + /// Looks up a localized string similar to Could not resolve DataTransfer state store account for region [{0}].. /// internal static string DataTransferStateStoreNotResolved -#pragma warning restore CS1570 // XML comment has badly formed XML { get { @@ -4567,5 +4630,148 @@ internal static string InvalidMongoDatabaseName return ResourceManager.GetString("InvalidMongoDatabaseName", resourceCulture); } } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). + /// + internal static string KeyVaultAuthenticationFailureRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultAuthenticationFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). + /// + internal static string KeyVaultWrapUnwrapFailureRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultWrapUnwrapFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to the correspondent key is not found on the specified Key Vault. + /// + internal static string KeyVaultKeyNotFoundRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultKeyNotFoundRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the correspondent Azure Key Vault was not found. + /// + internal static string KeyVaultNotFoundRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultNotFoundRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). + /// + internal static string KeyVaultDNSNotResolvedRevokeMessage + { + get + { + return ResourceManager.GetString("KeyVaultDNSNotResolvedRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). + /// + internal static string AadClientCredentialsGrantFailureRevokeMessage + { + get + { + return ResourceManager.GetString("AadClientCredentialsGrantFailureRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). + /// + internal static string UndefinedDefaultIdentityRevokeMessage + { + get + { + return ResourceManager.GetString("UndefinedDefaultIdentityRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). + /// + internal static string InvalidKeyVaultKeyURIRevokeMessage + { + get + { + return ResourceManager.GetString("InvalidKeyVaultKeyURIRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). + /// + internal static string NspOutboundDeniedRevokeMessage + { + get + { + return ResourceManager.GetString("NspOutboundDeniedRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide + /// + internal static string UnknownSubstatusCodeRevokeMessage + { + get + { + return ResourceManager.GetString("UnknownSubstatusCodeRevokeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your account has access to the customer managed key. + /// + internal static string CmkAccountIsNotRevoked + { + get + { + return ResourceManager.GetString("CmkAccountIsNotRevoked", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set EnableDataMaskingPolicy on an account with Log Store features. + /// + internal static string EnableDataMaskingPolicyAndEnableLogStoreNotSupported + { + get + { + return ResourceManager.GetString("EnableDataMaskingPolicyAndEnableLogStoreNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to DataMaskingPolicy is not supported on this account type. + /// + internal static string DataMaskingPolicyNotSupported + { + get + { + return ResourceManager.GetString("DataMaskingPolicyNotSupported", resourceCulture); + } + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/RMResources.resx b/Microsoft.Azure.Cosmos/src/RMResources.resx index a630919dc0..2e85bb5a71 100644 --- a/Microsoft.Azure.Cosmos/src/RMResources.resx +++ b/Microsoft.Azure.Cosmos/src/RMResources.resx @@ -744,6 +744,9 @@ Cannot offline write region when automatic failover is not enabled + + Federation {0} and region {1} are not matching. + Cannot add additional regions, since database account provision failed. @@ -1195,6 +1198,9 @@ If you would like to serve this query through continuation tokens, then please r Cannot authorize request since the [Action] to authorize was not found. + + Cross tenant CMK database account doesn't support using delegated identity as the default identity. + System database account {0} cannot be created with Continuous backup mode {0} = GlobalDatabaseAccountId @@ -1238,7 +1244,7 @@ If you would like to serve this query through continuation tokens, then please r The requested scope contains unexpected segments. - + Cannot perform failover as it is disabled for the account. @@ -1322,8 +1328,8 @@ If you would like to serve this query through continuation tokens, then please r Cross-tenant CMK is not supported with System Assigned identities as Default identities. Please use an User Assigned Identity instead. - - Federation cap action is not currently supported. + + The CapUncapMetadata action '{0}' is not currently supported. The given default identity for {0} is not valid. The format for the default identity is not valid, please use 'FirstPartyIdentity'/'SystemAssignedIdentity'/'UserAssignedIdentity=<UA_resource_id>' @@ -1337,4 +1343,62 @@ If you would like to serve this query through continuation tokens, then please r The given default identity for {0} is not valid. The default identity points to an user identity that does not exist in {0}. + + Access to your account is currently revoked because the Azure Cosmos DB service is unable to obtain the AAD authentication token for the account's default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-active-directory-token-acquisition-error ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB account's key vault key URI does not follow the expected format; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#improper-syntax-detected-on-the-key-vault-uri-property ({0}). + + + Access to your account is currently revoked because the current default identity no longer has permission to the associated Key Vault key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#default-identity-is-unauthorized-to-access-the-azure-key-vault-key ({0}). + + + Access to your account is currently revoked because the Azure Key Vault DNS name specified by the account's keyvaultkeyuri property could not be resolved; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#unable-to-resolve-the-key-vaults-dns ({0}). + + + Access to your account is currently revoked because the correspondent key is not found on the specified Key Vault; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). + + + Access to your account is currently revoked because the correspondent Azure Key Vault was not found; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#azure-key-vault-resource-not-found ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB service is unable to wrap or unwrap the key; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#internal-unwrapping-procedure-error ({0}). + + + Access to your account is currently revoked because the Azure Cosmos DB account has an undefined default identity; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide#invalid-azure-cosmos-db-default-identity ({0}). + + + Access to your account is currently revoked because the access rules are blocking outbound requests to the Azure Key Vault service; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide ({0}). + + + Access to your account is currently revoked; for more details about this error and how to restore access to your account please visit https://learn.microsoft.com/en-us/azure/cosmos-db/cmk-troubleshooting-guide + + + Access to the configured customer managed key confirmed. + + + Web socket requests are not supported + + + Sorry, we are currently experiencing high demand in {0} region, and cannot fulfill your request at this time. Please retry after sometime. If the problem persists, please reach out to support. + {0} = Location + + + Enable TieredStorageV1 and Enable Multiple write locations are not supported together on GlobalDatabaseAccount. + + + Dynamic Data Masking is not supported with Continuous Backup/Analytical Store/Materialized View/Full Fidelity Change Feed. + + + Dynamic Data Masking Policy is not supported on this account type. + + + Enable OnlyColdStorageContainersInAccount V1 and EnableMaterializedViews are not supported together on GlobalDatabaseAccount. + + + The CapUncapMetadata source '{0}' is invalid. + + + The federation document for the federation {0} is in an invalid format. + \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs index e8d4c602ff..dd24f3e45e 100644 --- a/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/RequestOptions/RequestOptions.cs @@ -69,6 +69,13 @@ public class RequestOptions /// public CosmosThresholdOptions CosmosThresholdOptions { get; set; } + /// + /// List of regions to be excluded routing the request to. + /// This can be used to route a request to a specific region by excluding all other regions. + /// If all regions are excluded, then the request will be routed to the primary/hub region. + /// + public List ExcludeRegions { get; set; } + /// /// Gets or sets the boolean to use effective partition key routing in the cosmos db request. /// diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs index 2978d741bf..5b6f188e89 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/Container.cs @@ -470,6 +470,13 @@ public abstract Task> ReadItemAsync( /// Check the HTTP status code on the response to check if the operation failed. /// /// https://aka.ms/cosmosdb-dot-net-exceptions#stream-api + /// + /// + /// Upsert result i.e. creation or replace can be identified by the status code: + /// 201 - item created + /// 200 - item replaced + /// + /// /// /// Upsert a Stream containing the item to Cosmos /// @@ -506,6 +513,13 @@ public abstract Task UpsertItemStreamAsync( /// (Optional) representing request cancellation. /// The that was upserted contained within a object representing the service response for the asynchronous operation. /// https://aka.ms/cosmosdb-dot-net-exceptions#typed-api + /// + /// + /// Upsert result i.e. creation or replace can be identified by the status code: + /// 201 - item created + /// 200 - item replaced + /// + /// /// /// /// > ReadManyItemsAsync( cancellationToken); } - /// - /// Used in the compute gateway to support legacy gateway interface. - /// - public override async Task TryExecuteQueryAsync( - QueryFeatures supportedQueryFeatures, - QueryDefinition queryDefinition, - string continuationToken, - FeedRangeInternal feedRangeInternal, - QueryRequestOptions requestOptions, - GeospatialType geospatialType, - CancellationToken cancellationToken = default) - { - if (queryDefinition == null) - { - throw new ArgumentNullException(nameof(queryDefinition)); - } - - if (requestOptions == null) - { - throw new ArgumentNullException(nameof(requestOptions)); - } - - if (feedRangeInternal != null) - { - // The user has scoped down to a physical partition or logical partition. - // In either case let the query execute as a passthrough. - QueryIterator passthroughQueryIterator = QueryIterator.Create( - containerCore: this, - client: this.queryClient, - clientContext: this.ClientContext, - sqlQuerySpec: queryDefinition.ToSqlQuerySpec(), - continuationToken: continuationToken, - feedRangeInternal: feedRangeInternal, - queryRequestOptions: requestOptions, - resourceLink: this.LinkUri, - isContinuationExpected: false, - allowNonValueAggregateQuery: true, - forcePassthrough: true, // Forcing a passthrough, since we don't want to get the query plan nor try to rewrite it. - partitionedQueryExecutionInfo: null); - - return new QueryPlanIsSupportedResult(passthroughQueryIterator); - } - - cancellationToken.ThrowIfCancellationRequested(); - - Documents.PartitionKeyDefinition partitionKeyDefinition; - if (requestOptions.Properties != null - && requestOptions.Properties.TryGetValue("x-ms-query-partitionkey-definition", out object partitionKeyDefinitionObject)) - { - if (!(partitionKeyDefinitionObject is Documents.PartitionKeyDefinition definition)) - { - throw new ArgumentException( - "partitionkeydefinition has invalid type", - nameof(partitionKeyDefinitionObject)); - } - - partitionKeyDefinition = definition; - } - else - { - ContainerQueryProperties containerQueryProperties = await this.queryClient.GetCachedContainerQueryPropertiesAsync( - this.LinkUri, - requestOptions.PartitionKey, - NoOpTrace.Singleton, - cancellationToken); - partitionKeyDefinition = containerQueryProperties.PartitionKeyDefinition; - } - - QueryPlanHandler queryPlanHandler = new QueryPlanHandler(this.queryClient); - - TryCatch<(PartitionedQueryExecutionInfo queryPlan, bool supported)> tryGetQueryInfoAndIfSupported = await queryPlanHandler.TryGetQueryInfoAndIfSupportedAsync( - supportedQueryFeatures, - queryDefinition.ToSqlQuerySpec(), - ResourceType.Document, - partitionKeyDefinition, - requestOptions.PartitionKey.HasValue, - useSystemPrefix: QueryIterator.IsSystemPrefixExpected(requestOptions), - geospatialType: geospatialType, - cancellationToken); - - if (tryGetQueryInfoAndIfSupported.Failed) - { - return new FailedToGetQueryPlanResult(tryGetQueryInfoAndIfSupported.Exception); - } - - (PartitionedQueryExecutionInfo queryPlan, bool supported) = tryGetQueryInfoAndIfSupported.Result; - TryExecuteQueryResult tryExecuteQueryResult; - if (supported) - { - QueryIterator queryIterator = QueryIterator.Create( - containerCore: this, - client: this.queryClient, - clientContext: this.ClientContext, - sqlQuerySpec: queryDefinition.ToSqlQuerySpec(), - continuationToken: continuationToken, - feedRangeInternal: feedRangeInternal, - queryRequestOptions: requestOptions, - resourceLink: this.LinkUri, - isContinuationExpected: false, - allowNonValueAggregateQuery: true, - forcePassthrough: false, - partitionedQueryExecutionInfo: queryPlan); - - tryExecuteQueryResult = new QueryPlanIsSupportedResult(queryIterator); - } - else - { - tryExecuteQueryResult = new QueryPlanNotSupportedResult(queryPlan); - } - - return tryExecuteQueryResult; - } - public override FeedIterator GetItemQueryIterator( string queryText = null, string continuationToken = null, @@ -833,8 +720,8 @@ public override FeedIteratorInternal GetItemQueryStreamIteratorInternal( resourceLink: this.LinkUri, isContinuationExpected: isContinuationExcpected, allowNonValueAggregateQuery: true, - forcePassthrough: false, - partitionedQueryExecutionInfo: null); + partitionedQueryExecutionInfo: null, + resourceType: ResourceType.Document); } public override FeedIteratorInternal GetReadFeedIterator( @@ -871,8 +758,8 @@ public override FeedIteratorInternal GetReadFeedIterator( resourceLink: resourceLink, isContinuationExpected: false, allowNonValueAggregateQuery: true, - forcePassthrough: false, - partitionedQueryExecutionInfo: null); + partitionedQueryExecutionInfo: null, + resourceType: resourceType); } else { diff --git a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs index 920fc5d694..dc532f6977 100644 --- a/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs +++ b/Microsoft.Azure.Cosmos/src/Resource/Container/ContainerInternal.cs @@ -65,15 +65,6 @@ public abstract Task>> GetPartitionKeyPathTo public abstract Task GetRoutingMapAsync(CancellationToken cancellationToken); - public abstract Task TryExecuteQueryAsync( - QueryFeatures supportedQueryFeatures, - QueryDefinition queryDefinition, - string continuationToken, - FeedRangeInternal feedRangeInternal, - QueryRequestOptions requestOptions, - GeospatialType geospatialType, - CancellationToken cancellationToken = default); - public abstract FeedIterator GetStandByFeedIterator( string continuationToken = default, int? maxItemCount = default, diff --git a/Microsoft.Azure.Cosmos/src/RetryPolicy.cs b/Microsoft.Azure.Cosmos/src/RetryPolicy.cs index 4ec05a3b65..47e64f0cbc 100644 --- a/Microsoft.Azure.Cosmos/src/RetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/RetryPolicy.cs @@ -13,17 +13,19 @@ internal sealed class RetryPolicy : IRetryPolicyFactory private readonly GlobalPartitionEndpointManager partitionKeyRangeLocationCache; private readonly GlobalEndpointManager globalEndpointManager; private readonly bool enableEndpointDiscovery; + private readonly bool isPertitionLevelFailoverEnabled; private readonly RetryOptions retryOptions; /// /// Initialize the instance of the RetryPolicy class /// public RetryPolicy( - GlobalEndpointManager globalEndpointManager, + GlobalEndpointManager globalEndpointManager, ConnectionPolicy connectionPolicy, GlobalPartitionEndpointManager partitionKeyRangeLocationCache) { this.enableEndpointDiscovery = connectionPolicy.EnableEndpointDiscovery; + this.isPertitionLevelFailoverEnabled = connectionPolicy.EnablePartitionLevelFailover; this.globalEndpointManager = globalEndpointManager; this.retryOptions = connectionPolicy.RetryOptions; this.partitionKeyRangeLocationCache = partitionKeyRangeLocationCache; @@ -37,10 +39,11 @@ public IDocumentClientRetryPolicy GetRequestPolicy() ClientRetryPolicy clientRetryPolicy = new ClientRetryPolicy( this.globalEndpointManager, this.partitionKeyRangeLocationCache, + this.retryOptions, this.enableEndpointDiscovery, - this.retryOptions); + this.isPertitionLevelFailoverEnabled); return clientRetryPolicy; } } -} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs index 9fb908d83f..4025863d19 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/AsyncCacheNonBlocking.cs @@ -9,7 +9,6 @@ namespace Microsoft.Azure.Cosmos using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Cosmos.Core.Trace; - using Microsoft.Azure.Cosmos.Tracing.TraceData; /// /// This is a thread safe AsyncCache that allows refreshing values in the background. @@ -179,21 +178,26 @@ public bool TryRemove(TKey key) /// /// Refreshes the async non blocking cache on-demand for the given - /// and caches the result for later usage. + /// and caches the result for later usage. Note that this method doesn't control the number + /// of tasks created in parallel, and the concurrency needed to be controlled at the caller. /// /// The requested key to be refreshed. /// A func delegate to be invoked at a later point of time. - public async Task RefreshAsync( + public void Refresh( TKey key, Func> singleValueInitFunc) { if (this.values.TryGetValue(key, out AsyncLazyWithRefreshTask initialLazyValue)) { - await this.UpdateCacheAndGetValueFromBackgroundTaskAsync( - key: key, - initialValue: initialLazyValue, - callbackDelegate: singleValueInitFunc, - operationName: nameof(RefreshAsync)); + Task backgroundRefreshTask = this.GetAsync( + key: key, + singleValueInitFunc: singleValueInitFunc, + forceRefresh: (_) => true); + + Task continuationTask = backgroundRefreshTask + .ContinueWith( + task => DefaultTrace.TraceVerbose("Failed to refresh addresses in the background with exception: {0}", task.Exception), + TaskContinuationOptions.OnlyOnFaulted); } } @@ -250,8 +254,8 @@ private sealed class AsyncLazyWithRefreshTask { private readonly CancellationToken cancellationToken; private readonly Func> createValueFunc; - private readonly object valueLock = new object(); - private readonly object removedFromCacheLock = new object(); + private readonly object valueLock = new (); + private readonly object removedFromCacheLock = new (); private bool removedFromCache = false; private Task value; diff --git a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs index 8bc429070e..f2012fe0bc 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GatewayAddressCache.cs @@ -50,12 +50,14 @@ internal class GatewayAddressCache : IAddressCache, IDisposable private readonly ICosmosAuthorizationTokenProvider tokenProvider; private readonly bool enableTcpConnectionEndpointRediscovery; + private readonly SemaphoreSlim semaphore; private readonly CosmosHttpClient httpClient; private readonly bool isReplicaAddressValidationEnabled; private Tuple masterPartitionAddressCache; private DateTime suboptimalMasterPartitionTimestamp; private bool disposedValue; + private bool validateUnknownReplicas; private IOpenConnectionsHandler openConnectionsHandler; public GatewayAddressCache( @@ -90,8 +92,10 @@ public GatewayAddressCache( Constants.Properties.Protocol, GatewayAddressCache.ProtocolString(this.protocol)); + this.semaphore = new SemaphoreSlim(1, 1); this.openConnectionsHandler = openConnectionsHandler; this.isReplicaAddressValidationEnabled = replicaAddressValidationEnabled; + this.validateUnknownReplicas = false; } public Uri ServiceEndpoint => this.serviceEndpoint; @@ -120,6 +124,14 @@ public async Task OpenConnectionsAsync( List tasks = new (); int batchSize = GatewayAddressCache.DefaultBatchSize; + // By design, the Unknown replicas are validated only when the following two conditions meet: + // 1) The CosmosClient is initiated using the CreateAndInitializaAsync() flow. + // 2) The advanced replica selection feature enabled. + if (shouldOpenRntbdChannels) + { + this.validateUnknownReplicas = true; + } + #if !(NETSTANDARD15 || NETSTANDARD16) #if NETSTANDARD20 // GetEntryAssembly returns null when loaded from native netstandard2.0 @@ -302,11 +314,12 @@ public async Task TryGetAddressesAsync( .ReplicaTransportAddressUris .Any(x => x.ShouldRefreshHealthStatus())) { - Task refreshAddressesInBackgroundTask = Task.Run(async () => + bool slimAcquired = await this.semaphore.WaitAsync(0); + try { - try + if (slimAcquired) { - await this.serverPartitionAddressCache.RefreshAsync( + this.serverPartitionAddressCache.Refresh( key: partitionKeyRangeIdentity, singleValueInitFunc: (currentCachedValue) => this.GetAddressesForRangeIdAsync( request, @@ -315,14 +328,21 @@ await this.serverPartitionAddressCache.RefreshAsync( partitionKeyRangeIdentity.PartitionKeyRangeId, forceRefresh: true)); } - catch (Exception ex) + else { - DefaultTrace.TraceWarning("Failed to refresh addresses in the background for the collection rid: {0} with exception: {1}. '{2}'", + DefaultTrace.TraceVerbose("Failed to refresh addresses in the background for the collection rid: {0}, partition key range id: {1}, because the semaphore is already acquired. '{2}'", partitionKeyRangeIdentity.CollectionRid, - ex, + partitionKeyRangeIdentity.PartitionKeyRangeId, System.Diagnostics.Trace.CorrelationManager.ActivityId); } - }); + } + finally + { + if (slimAcquired) + { + this.semaphore.Release(); + } + } } return addresses; @@ -1008,18 +1028,26 @@ private static PartitionAddressInformation MergeAddresses( /// Returns a list of needed to validate their health status. Validating /// a uri is done by opening Rntbd connection to the backend replica, which is a costly operation by nature. Therefore /// vaidating both Unhealthy and Unknown replicas at the same time could impose a high CPU utilization. To avoid this - /// situation, the RntbdOpenConnectionHandler has good concurrency control mechanism to open the connections gracefully/>. + /// situation, the RntbdOpenConnectionHandler has good concurrency control mechanism to open the connections gracefully. + /// By default, this method only returns the Unhealthy replicas that requires to validate it's connectivity status. The + /// Unknown replicas are validated only when the CosmosClient is initiated using the CreateAndInitializaAsync() flow. /// /// A read only list of s. /// A list of that needs to validate their status. private IEnumerable GetAddressesNeededToValidateStatus( IReadOnlyList transportAddresses) { - return transportAddresses - .Where(address => address + return this.validateUnknownReplicas + ? transportAddresses + .Where(address => address + .GetCurrentHealthState() + .GetHealthStatus() is + TransportAddressHealthState.HealthStatus.UnhealthyPending or + TransportAddressHealthState.HealthStatus.Unknown) + : transportAddresses + .Where(address => address .GetCurrentHealthState() .GetHealthStatus() is - TransportAddressHealthState.HealthStatus.Unknown or TransportAddressHealthState.HealthStatus.UnhealthyPending); } diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs index 956212d5a2..e12d99255d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalEndpointManager.cs @@ -89,9 +89,11 @@ public GlobalEndpointManager(IDocumentClientInternal owner, ConnectionPolicy con } } - public ReadOnlyCollection ReadEndpoints => this.locationCache.ReadEndpoints; + public ReadOnlyCollection ReadEndpoints => this.locationCache.ReadEndpoints; + + public ReadOnlyCollection AccountReadEndpoints => this.locationCache.AccountReadEndpoints; - public ReadOnlyCollection WriteEndpoints => this.locationCache.WriteEndpoints; + public ReadOnlyCollection WriteEndpoints => this.locationCache.WriteEndpoints; public int PreferredLocationCount => this.connectionPolicy.PreferredLocations != null ? this.connectionPolicy.PreferredLocations.Count : 0; @@ -360,6 +362,11 @@ public string GetLocation(Uri endpoint) return this.locationCache.GetLocation(endpoint); } + public ReadOnlyCollection GetApplicableEndpoints(DocumentServiceRequest request, bool isReadRequest) + { + return this.locationCache.GetApplicableEndpoints(request, isReadRequest); + } + public bool TryGetLocationForGatewayDiagnostics(Uri endpoint, out string regionName) { return this.locationCache.TryGetLocationForGatewayDiagnostics(endpoint, out regionName); diff --git a/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs b/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs index a4ab1221e6..fe2e256601 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/GlobalPartitionEndpointManagerCore.cs @@ -134,11 +134,20 @@ public override bool TryMarkEndpointUnavailableForPartitionKeyRange( PartitionKeyRangeFailoverInfo partionFailover = this.PartitionKeyRangeToLocation.Value.GetOrAdd( partitionKeyRange, - (_) => new PartitionKeyRangeFailoverInfo(failedLocation)); - + (_) => new PartitionKeyRangeFailoverInfo(failedLocation)); + + // For any single master write accounts, the next locations to fail over will be the read regions configured at the account level. + // For multi master write accounts, since all the regions are treated as write regions, the next locations to fail over + // will be the preferred read regions that are configured in the application preferred regions in the CosmosClientOptions. + bool isSingleMasterWriteAccount = !this.globalEndpointManager.CanUseMultipleWriteLocations(request); + + ReadOnlyCollection nextLocations = isSingleMasterWriteAccount + ? this.globalEndpointManager.AccountReadEndpoints + : this.globalEndpointManager.ReadEndpoints; + // Will return true if it was able to update to a new region if (partionFailover.TryMoveNextLocation( - locations: this.globalEndpointManager.ReadEndpoints, + locations: nextLocations, failedLocation: failedLocation)) { DefaultTrace.TraceInformation("Partition level override added to new location. PartitionKeyRange: {0}, failedLocation: {1}, new location: {2}", diff --git a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs index dd3d8a2611..83f49cf0de 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/IGlobalEndpointManager.cs @@ -13,6 +13,8 @@ internal interface IGlobalEndpointManager : IDisposable { ReadOnlyCollection ReadEndpoints { get; } + ReadOnlyCollection AccountReadEndpoints { get; } + ReadOnlyCollection WriteEndpoints { get; } int PreferredLocationCount { get; } diff --git a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs index 9c6308d8b6..88a369bd2d 100644 --- a/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs +++ b/Microsoft.Azure.Cosmos/src/Routing/LocationCache.cs @@ -31,6 +31,7 @@ internal sealed class LocationCache private readonly TimeSpan unavailableLocationsExpirationTime; private readonly int connectionLimit; private readonly ConcurrentDictionary locationUnavailablityInfoByEndpoint; + private readonly RegionNameMapper regionNameMapper; private DatabaseAccountLocationsInfo locationInfo; private DateTime lastCacheUpdateTimestamp; @@ -54,6 +55,7 @@ public LocationCache( this.lastCacheUpdateTimestamp = DateTime.MinValue; this.enableMultipleWriteLocations = false; this.unavailableLocationsExpirationTime = TimeSpan.FromSeconds(LocationCache.DefaultUnavailableLocationsExpirationTimeInSeconds); + this.regionNameMapper = new RegionNameMapper(); #if !(NETSTANDARD15 || NETSTANDARD16) #if NETSTANDARD20 @@ -101,6 +103,11 @@ public ReadOnlyCollection ReadEndpoints } } + /// + /// Gets list of account level read endpoints. + /// + public ReadOnlyCollection AccountReadEndpoints => this.locationInfo.AccountReadEndpoints; + /// /// Gets list of write endpoints ordered by /// 1. Preferred location @@ -276,7 +283,7 @@ public Uri ResolveServiceEndpoint(DocumentServiceRequest request) } else { - ReadOnlyCollection endpoints = request.OperationType.IsWriteOperation() ? this.WriteEndpoints : this.ReadEndpoints; + ReadOnlyCollection endpoints = this.GetApplicableEndpoints(request, !request.OperationType.IsWriteOperation()); locationEndpointToRoute = endpoints[locationIndex % endpoints.Count]; } @@ -284,6 +291,64 @@ public Uri ResolveServiceEndpoint(DocumentServiceRequest request) return locationEndpointToRoute; } + public ReadOnlyCollection GetApplicableEndpoints(DocumentServiceRequest request, bool isReadRequest) + { + ReadOnlyCollection endpoints = isReadRequest ? this.ReadEndpoints : this.WriteEndpoints; + + if (request.RequestContext.ExcludeRegions == null || request.RequestContext.ExcludeRegions.Count == 0) + { + return endpoints; + } + + return this.GetApplicableEndpoints( + endpoints, + isReadRequest ? this.locationInfo.AvailableReadEndpointByLocation : this.locationInfo.AvailableWriteEndpointByLocation, + this.defaultEndpoint, + request.RequestContext.ExcludeRegions); + } + + /// + /// Gets applicable endpoints for a request, if there are no applicable endpoints, returns the fallback endpoint + /// + /// + /// + /// + /// + /// a list of applicable endpoints for a request + private ReadOnlyCollection GetApplicableEndpoints( + IReadOnlyList endpoints, + ReadOnlyDictionary regionNameByEndpoint, + Uri fallbackEndpoint, + IReadOnlyList excludeRegions) + { + List applicableEndpoints = new List(endpoints.Count); + HashSet excludeUris = new HashSet(); + + foreach (string region in excludeRegions) + { + string normalizedRegionName = this.regionNameMapper.GetCosmosDBRegionName(region); + if (regionNameByEndpoint.ContainsKey(normalizedRegionName)) + { + excludeUris.Add(regionNameByEndpoint[normalizedRegionName]); + } + } + + foreach (Uri endpoint in endpoints) + { + if (!excludeUris.Contains(endpoint)) + { + applicableEndpoints.Add(endpoint); + } + } + + if (applicableEndpoints.Count == 0) + { + applicableEndpoints.Add(fallbackEndpoint); + } + + return new ReadOnlyCollection(applicableEndpoints); + } + public bool ShouldRefreshEndpoints(out bool canRefreshInBackground) { canRefreshInBackground = true; @@ -491,20 +556,35 @@ private void UpdateLocationCache( if (readLocations != null) { - ReadOnlyCollection availableReadLocations; - nextLocationInfo.AvailableReadEndpointByLocation = this.GetEndpointByLocation(readLocations, out availableReadLocations); + nextLocationInfo.AvailableReadEndpointByLocation = this.GetEndpointByLocation( + readLocations, + out ReadOnlyCollection availableReadLocations); + nextLocationInfo.AvailableReadLocations = availableReadLocations; + nextLocationInfo.AccountReadEndpoints = nextLocationInfo.AvailableReadEndpointByLocation.Select(x => x.Value).ToList().AsReadOnly(); } if (writeLocations != null) { - ReadOnlyCollection availableWriteLocations; - nextLocationInfo.AvailableWriteEndpointByLocation = this.GetEndpointByLocation(writeLocations, out availableWriteLocations); + nextLocationInfo.AvailableWriteEndpointByLocation = this.GetEndpointByLocation( + writeLocations, + out ReadOnlyCollection availableWriteLocations); + nextLocationInfo.AvailableWriteLocations = availableWriteLocations; } - nextLocationInfo.WriteEndpoints = this.GetPreferredAvailableEndpoints(nextLocationInfo.AvailableWriteEndpointByLocation, nextLocationInfo.AvailableWriteLocations, OperationType.Write, this.defaultEndpoint); - nextLocationInfo.ReadEndpoints = this.GetPreferredAvailableEndpoints(nextLocationInfo.AvailableReadEndpointByLocation, nextLocationInfo.AvailableReadLocations, OperationType.Read, nextLocationInfo.WriteEndpoints[0]); + nextLocationInfo.WriteEndpoints = this.GetPreferredAvailableEndpoints( + endpointsByLocation: nextLocationInfo.AvailableWriteEndpointByLocation, + orderedLocations: nextLocationInfo.AvailableWriteLocations, + expectedAvailableOperation: OperationType.Write, + fallbackEndpoint: this.defaultEndpoint); + + nextLocationInfo.ReadEndpoints = this.GetPreferredAvailableEndpoints( + endpointsByLocation: nextLocationInfo.AvailableReadEndpointByLocation, + orderedLocations: nextLocationInfo.AvailableReadLocations, + expectedAvailableOperation: OperationType.Read, + fallbackEndpoint: nextLocationInfo.WriteEndpoints[0]); + this.lastCacheUpdateTimestamp = DateTime.UtcNow; DefaultTrace.TraceInformation("Current WriteEndpoints = ({0}) ReadEndpoints = ({1})", @@ -534,8 +614,7 @@ private ReadOnlyCollection GetPreferredAvailableEndpoints(ReadOnlyDictionar foreach (string location in currentLocationInfo.PreferredLocations) { - Uri endpoint; - if (endpointsByLocation.TryGetValue(location, out endpoint)) + if (endpointsByLocation.TryGetValue(location, out Uri endpoint)) { if (this.IsEndpointUnavailable(endpoint, expectedAvailableOperation)) { @@ -560,9 +639,8 @@ private ReadOnlyCollection GetPreferredAvailableEndpoints(ReadOnlyDictionar { foreach (string location in orderedLocations) { - Uri endpoint; if (!string.IsNullOrEmpty(location) && // location is empty during manual failover - endpointsByLocation.TryGetValue(location, out endpoint)) + endpointsByLocation.TryGetValue(location, out Uri endpoint)) { endpoints.Add(endpoint); } @@ -634,6 +712,7 @@ public DatabaseAccountLocationsInfo(ReadOnlyCollection preferredLocation this.AvailableWriteEndpointByLocation = new ReadOnlyDictionary(new Dictionary(StringComparer.OrdinalIgnoreCase)); this.AvailableReadEndpointByLocation = new ReadOnlyDictionary(new Dictionary(StringComparer.OrdinalIgnoreCase)); this.WriteEndpoints = new List() { defaultEndpoint }.AsReadOnly(); + this.AccountReadEndpoints = new List() { defaultEndpoint }.AsReadOnly(); this.ReadEndpoints = new List() { defaultEndpoint }.AsReadOnly(); } @@ -645,6 +724,7 @@ public DatabaseAccountLocationsInfo(DatabaseAccountLocationsInfo other) this.AvailableWriteEndpointByLocation = other.AvailableWriteEndpointByLocation; this.AvailableReadEndpointByLocation = other.AvailableReadEndpointByLocation; this.WriteEndpoints = other.WriteEndpoints; + this.AccountReadEndpoints = other.AccountReadEndpoints; this.ReadEndpoints = other.ReadEndpoints; } @@ -655,6 +735,7 @@ public DatabaseAccountLocationsInfo(DatabaseAccountLocationsInfo other) public ReadOnlyDictionary AvailableReadEndpointByLocation { get; set; } public ReadOnlyCollection WriteEndpoints { get; set; } public ReadOnlyCollection ReadEndpoints { get; set; } + public ReadOnlyCollection AccountReadEndpoints { get; set; } } [Flags] diff --git a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs index 748f81833a..3c48b1f5ab 100644 --- a/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs +++ b/Microsoft.Azure.Cosmos/src/Util/ConfigurationManager.cs @@ -9,12 +9,19 @@ namespace Microsoft.Azure.Cosmos internal static class ConfigurationManager { /// - /// A read-only string containing the environment variablename for enabling replica validation. - /// This will eventually be removed oncereplica valdiatin is enabled by default for both preview + /// A read-only string containing the environment variable name for enabling replica validation. + /// This will eventually be removed once replica valdiatin is enabled by default for both preview /// and GA. /// internal static readonly string ReplicaConnectivityValidationEnabled = "AZURE_COSMOS_REPLICA_VALIDATION_ENABLED"; + /// + /// A read-only string containing the environment variable name for enabling per partition automatic failover. + /// This will eventually be removed once per partition automatic failover is enabled by default for both preview + /// and GA. + /// + internal static readonly string PartitionLevelFailoverEnabled = "AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED"; + public static T GetEnvironmentVariable(string variable, T defaultValue) { string value = Environment.GetEnvironmentVariable(variable); @@ -37,8 +44,6 @@ public static T GetEnvironmentVariable(string variable, T defaultValue) public static bool IsReplicaAddressValidationEnabled( ConnectionPolicy connectionPolicy) { - bool replicaValidationDefaultValue = false; - if (connectionPolicy != null && connectionPolicy.EnableAdvancedReplicaSelectionForTcp.HasValue) { @@ -48,7 +53,24 @@ public static bool IsReplicaAddressValidationEnabled( return ConfigurationManager .GetEnvironmentVariable( variable: ConfigurationManager.ReplicaConnectivityValidationEnabled, - defaultValue: replicaValidationDefaultValue); + defaultValue: true); + } + + /// + /// Gets the boolean value of the partition level failover environment variable. Note that, partition level failover + /// is disabled by default for both preview and GA releases. The user can set the respective environment variable + /// 'AZURE_COSMOS_PARTITION_LEVEL_FAILOVER_ENABLED' to override the value for both preview and GA. The method will + /// eventually be removed, once partition level failover is enabled by default for both preview and GA. + /// + /// A boolean field containing the default value for partition level failover. + /// A boolean flag indicating if partition level failover is enabled. + public static bool IsPartitionLevelFailoverEnabled( + bool defaultValue) + { + return ConfigurationManager + .GetEnvironmentVariable( + variable: ConfigurationManager.PartitionLevelFailoverEnabled, + defaultValue: defaultValue); } } } diff --git a/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs b/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs index 1892160c81..4159928f46 100644 --- a/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/AuthorizationTokenType.cs @@ -22,6 +22,7 @@ internal enum AuthorizationTokenType AadToken, CompoundToken, SasToken, + TokenCredential } internal static class AuthorizationTokenTypeExtensions diff --git a/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs b/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs index 2e0e965b1b..e24ef1a939 100644 --- a/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/BackoffRetryUtility.cs @@ -21,6 +21,9 @@ internal static class BackoffRetryUtility { public const string ExceptionSourceToIgnoreForIgnoreForRetry = "BackoffRetryUtility"; + /// + /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. + /// public static Task ExecuteAsync( Func> callbackMethod, IRetryPolicy retryPolicy, @@ -129,6 +132,9 @@ public static Task ExecuteAsync( /// /// Common implementation that handles all the different possible configurations. /// + /// + /// On an exception if this methiod is not attempting another retry it throws the last exception encountered. Not an Aggregation Exception of All Exceptions Encountered. + /// private static async Task ExecuteRetryAsync( Func> callbackMethod, Func> callbackMethodWithParam, @@ -154,75 +160,90 @@ private static async Task ExecuteRetryAsync( while (true) { - cancellationToken.ThrowIfCancellationRequested(); - ExceptionDispatchInfo exception; try { - if (callbackMethod != null) + cancellationToken.ThrowIfCancellationRequested(); + ExceptionDispatchInfo exception; + try { - return await callbackMethod(); + if (callbackMethod != null) + { + return await callbackMethod(); + } + else if (callbackMethodWithParam != null) + { + return await callbackMethodWithParam(param, cancellationToken); + } + + return await callbackMethodWithPolicy(policyArg1); } - else if (callbackMethodWithParam != null) + catch (Exception ex) { - return await callbackMethodWithParam(param, cancellationToken); - } + // this Yield is to "reset" the stack to avoid stack overflows in Framework + // and to keep the total size of the StackTrace down if we fail + await Task.Yield(); - return await callbackMethodWithPolicy(policyArg1); - } - catch (Exception ex) - { - await Task.Yield(); - exception = ExceptionDispatchInfo.Capture(ex); - } + exception = ExceptionDispatchInfo.Capture(ex); + } - ShouldRetryResult result; - if (retryPolicyWithArg != null) - { - ShouldRetryResult resultWithPolicy = await retryPolicyWithArg.ShouldRetryAsync(exception.SourceException, cancellationToken); + ShouldRetryResult result; + if (retryPolicyWithArg != null) + { + ShouldRetryResult resultWithPolicy = await retryPolicyWithArg.ShouldRetryAsync(exception.SourceException, cancellationToken); - policyArg1 = resultWithPolicy.PolicyArg1; - result = resultWithPolicy; - } - else - { - result = await retryPolicy.ShouldRetryAsync(exception.SourceException, cancellationToken); - } + policyArg1 = resultWithPolicy.PolicyArg1; + result = resultWithPolicy; + } + else + { + result = await retryPolicy.ShouldRetryAsync(exception.SourceException, cancellationToken); + } - result.ThrowIfDoneTrying(exception); + result.ThrowIfDoneTrying(exception); - TimeSpan backoffTime = result.BackoffTime; - bool hasBackoffAlternateCallback = inBackoffAlternateCallbackMethod != null || inBackoffAlternateCallbackMethodWithPolicy != null; + TimeSpan backoffTime = result.BackoffTime; + bool hasBackoffAlternateCallback = inBackoffAlternateCallbackMethod != null || inBackoffAlternateCallbackMethodWithPolicy != null; - if (hasBackoffAlternateCallback && result.BackoffTime >= minBackoffForInBackoffCallback) - { - ValueStopwatch stopwatch = ValueStopwatch.StartNew(); - TimeSpan elapsed; - try + if (hasBackoffAlternateCallback && result.BackoffTime >= minBackoffForInBackoffCallback) { - if (inBackoffAlternateCallbackMethod != null) + ValueStopwatch stopwatch = ValueStopwatch.StartNew(); + TimeSpan elapsed; + try + { + if (inBackoffAlternateCallbackMethod != null) + { + return await inBackoffAlternateCallbackMethod(); + } + + return await inBackoffAlternateCallbackMethodWithPolicy(policyArg1); + } + catch (Exception ex) { - return await inBackoffAlternateCallbackMethod(); + elapsed = stopwatch.Elapsed; + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), elapsed.TotalMilliseconds); } - return await inBackoffAlternateCallbackMethodWithPolicy(policyArg1); + backoffTime = result.BackoffTime > elapsed ? result.BackoffTime - elapsed : TimeSpan.Zero; } - catch (Exception ex) + + if (preRetryCallback != null) { - elapsed = stopwatch.Elapsed; - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), elapsed.TotalMilliseconds); + preRetryCallback(exception.SourceException); } - backoffTime = result.BackoffTime > elapsed ? result.BackoffTime - elapsed : TimeSpan.Zero; + if (backoffTime != TimeSpan.Zero) + { + await Task.Delay(backoffTime, cancellationToken); + } } - - if (preRetryCallback != null) + catch { - preRetryCallback(exception.SourceException); - } + // if we're going to completely fail, we want to toss all the async continuation + // stack frames so we don't have a gigantic stack trace (which has serious performance + // implications) + await Task.Yield(); - if (backoffTime != TimeSpan.Zero) - { - await Task.Delay(backoffTime, cancellationToken); + throw; } } } diff --git a/Microsoft.Azure.Cosmos/src/direct/Channel.cs b/Microsoft.Azure.Cosmos/src/direct/Channel.cs index 689d5eba27..b19888a90a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Channel.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Channel.cs @@ -40,7 +40,7 @@ public Channel( ChannelProperties channelProperties, bool localRegionRequest, SemaphoreSlim openingSlim, IChaosInterceptor chaosInterceptor = null, - Action onChannelOpen = null) + Action onChannelOpen = null) { Debug.Assert(channelProperties != null); this.dispatcher = new Dispatcher(serverUri, @@ -134,7 +134,7 @@ public bool Healthy private Guid ConnectionCorrelationId { get => this.dispatcher.ConnectionCorrelationId; } - private void Initialize(Guid activityId, Action onChannelOpen = null) + private void Initialize(Guid activityId, Action onChannelOpen = null) { this.ThrowIfDisposed(); this.stateLock.EnterWriteLock(); @@ -362,12 +362,12 @@ private void ThrowIfDisposed() } } - private async Task InitializeAsync(Guid activityId, Action onChannelOpen = null) + private async Task InitializeAsync(Guid activityId, Action onChannelOpen = null) { bool slimAcquired = false; try { - onChannelOpen?.Invoke(activityId, this.serverUri, this); + onChannelOpen?.Invoke(activityId, this.ConnectionCorrelationId, this.serverUri, this); this.openArguments.CommonArguments.SetTimeoutCode(TransportErrorCode.ChannelWaitingToOpenTimeout); slimAcquired = await this.openingSlim.WaitAsync(this.openArguments.OpenTimeout).ConfigureAwait(false); diff --git a/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs index 71ec5a0a55..589dd91d2d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ClientSideRequestStatistics.cs @@ -533,4 +533,5 @@ public void AppendToBuilder(StringBuilder stringBuilder) } } } -} \ No newline at end of file +} + diff --git a/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs b/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs new file mode 100644 index 0000000000..06ca5c0454 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/ComputedProperty.cs @@ -0,0 +1,85 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + using Newtonsoft.Json.Linq; + using System; + using System.Collections.Generic; + + /// + /// Represents computed property that belongs to a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class ComputedProperty : JsonSerializable, ICloneable + { + /// + /// Gets or sets the name of the computed property. + /// + /// + /// The name of the computed property. + /// + /// + /// Name of the computed property should be chosen such that it does not collide with any existing or future document properties. + /// + [JsonProperty(PropertyName = Constants.Properties.Name)] + public string Name + { + get + { + return base.GetValue(Constants.Properties.Name); + } + set + { + base.SetValue(Constants.Properties.Name, value); + } + } + + /// + /// Gets or sets the query for the computed property. + /// + /// + /// The query used to evaluate the value for the computed property. + /// + /// + /// For example: + /// SELECT VALUE LOWER(c.firstName) FROM c + /// + [JsonProperty(PropertyName = Constants.Properties.Query)] + public string Query + { + get + { + return base.GetValue(Constants.Properties.Query); + } + set + { + base.SetValue(Constants.Properties.Query, value); + } + } + + /// + internal override void Validate() + { + // See IncludedPath.cs implementation + base.Validate(); + base.GetValue(Constants.Properties.Name); + base.GetValue(Constants.Properties.Query); + } + + /// + /// Clones a ComputedProperty object + /// + /// + public object Clone() + { + return new ComputedProperty + { + Name = this.Name, + Query = this.Query + }; + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Connection.cs b/Microsoft.Azure.Cosmos/src/direct/Connection.cs index 8874d6e023..1298d88392 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Connection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Connection.cs @@ -125,7 +125,7 @@ public Connection( this.serverUri = serverUri; this.hostNameCertificateOverride = hostNameCertificateOverride; this.BufferProvider = new BufferProvider(); - this.dnsResolutionFunction = dnsResolutionFunction ?? Connection.ResolveHostAsync; + this.dnsResolutionFunction = dnsResolutionFunction ?? Connection.ResolveHostIncludingIPv6AddressesAsync; this.lastSendAttemptTime = DateTime.MinValue; this.lastSendTime = DateTime.MinValue; this.lastReceiveTime = DateTime.MinValue; @@ -984,14 +984,44 @@ await Connection.ConnectReuseAddrAsync( return Tuple.Create(await Connection.ConnectUnicastPortAsync(serverUri, address, connectionCorrelationId), false); } - internal static async Task ResolveHostAsync(string hostName) + /// + /// Wrapper method for that allows IPv6 addresses. + /// Used unless internal clients provide a version that might override decision to use IPv6 addresses. + /// + /// + /// + private static Task ResolveHostIncludingIPv6AddressesAsync(string hostName) => Connection.ResolveHostAsync(hostName, includeIPv6Addresses: true); + + internal static async Task ResolveHostAsync(string hostName, bool includeIPv6Addresses) { + // Using Linq for a cold path IPAddress[] serverAddresses = await Dns.GetHostAddressesAsync(hostName); + int serverAddressesCount = serverAddresses.Length; + + if (!includeIPv6Addresses) + { + // Exclude IPv6 addresses + serverAddressesCount = 0; + foreach (IPAddress ipAddress in serverAddresses) + { + if (ipAddress.AddressFamily == AddressFamily.InterNetwork) + { + serverAddresses[serverAddressesCount++] = ipAddress; + } + } + } + int addressIndex = 0; - if (serverAddresses.Length > 1) + if (serverAddressesCount > 1) { - addressIndex = Connection.rng.Value.Next(serverAddresses.Length); + addressIndex = Connection.rng.Value.Next(serverAddressesCount); } + + if (serverAddressesCount == 0) + { + throw new ArgumentOutOfRangeException($"DNS Resolve resulted in no internet addresses. includeIPv6Addresses: {includeIPv6Addresses}"); + } + return serverAddresses[addressIndex]; } diff --git a/Microsoft.Azure.Cosmos/src/direct/Constants.cs b/Microsoft.Azure.Cosmos/src/direct/Constants.cs index 5e39d91a09..0acba36987 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Constants.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Constants.cs @@ -128,6 +128,9 @@ public static class MongoServerVersion public const string Version3_6 = "3.6"; public const string Version4_0 = "4.0"; public const string Version4_2 = "4.2"; + public const string Version5_0 = "5.0"; + public const string Version6_0 = "6.0"; + public const string Version7_0 = "7.0"; } internal static class Indexing @@ -306,6 +309,7 @@ public static class Properties public const string IsManagedReadOnlyAccountKeyResourceStale = "isManagedReadOnlyAccountKeyResourceStale"; public const string UserName = "userName"; public const string Subscriptions = "subscriptions"; + public const string ResourceGroups = "resourceGroups"; public const string Providers = "providers"; public const string RestorableDatabaseAccounts = "restorableDatabaseAccounts"; public const string AsynchronousDeletionRetryCount = "asynchronousDeletionRetryCount"; @@ -313,11 +317,13 @@ public static class Properties public const string MasterValue = "masterValue"; public const string SecondaryValue = "secondaryValue"; - public const string IsSubscriptionInUse = "isSubscriptionInUse"; public const string ArmLocation = "armLocation"; public const string SubscriptionName = "subscriptionName"; + //Throughput Pool + public const string MaxThroughput = "maxThroughput"; + // Query public const string Query = "query"; public const string Parameters = "parameters"; @@ -446,13 +452,16 @@ public static class Properties // CapUncapMetadata public const string Source = "source"; - public const string Reason = "reason"; + public const string Reason = "reason"; public const string IncidentId = "incidentId"; // GeospatialConfig public const string GeospatialType = "type"; public const string GeospatialConfig = "geospatialConfig"; + // ComputedProperties + public const string ComputedProperties = "computedProperties"; + // Unique index. public const string UniqueKeyPolicy = "uniqueKeyPolicy"; public const string UniqueKeys = "uniqueKeys"; @@ -601,11 +610,14 @@ public static class Properties public const string UpdateBackupContainerMetadata = "updateBackupContainerMetadata"; public const string RestoreWithBuiltinDatabaseAccountPicker = "restoreWithBuiltinDatabaseAccountPicker"; public const string RestoreWithSourceGlobalDatabaseAccountInstanceId = "restoreWithSourceGlobalDatabaseAccountInstanceId"; + public const string RestoreWithTTLDisabled = "restoreWithTTLDisabled"; public const string DatabasesToRestore = "databasesToRestore"; public const string DatabaseName = "databaseName"; public const string CollectionNames = "collectionNames"; public const string GraphNames = "graphNames"; public const string TableNames = "tableNames"; + public const string RestoreTillEndOfLogChain = "restoreTillEndOfLogChain"; + public const int TimeToleranceForRestoreTillEndOfLogChain = 1000; //ms // Restore Properties public const string RestoreTimestampInUtc = "restoreTimestampInUtc"; @@ -643,7 +655,7 @@ public static class Properties public const string Message = "message"; public const string ErrorDetails = "errorDetails"; public const string AdditionalErrorInfo = "additionalErrorInfo"; - + //CassandraErrorResource. public const string Target = "target"; @@ -660,7 +672,10 @@ public static class Properties public const string AadToken = "aad"; public const string SasToken = "sas"; public const string TokenVersion = "1.0"; + public const string TokenVersionV2 = "2.0"; public const string AuthSchemaType = "type"; + public const string ResourceTokenV2Label = "ResourceTokenV2Label"; + public const string ResourceTokenV2Context = "ResourceTokenV2Context"; public const string AuthVersion = "ver"; public const string AuthSignature = "sig"; public const string readPermissionMode = "read"; @@ -706,6 +721,7 @@ public static class Properties public const string BitLockerKeysSettingType = "BitLockerKeysSettingType"; public const string BitLockerKeysRotationState = "BitLockerKeysRotationState"; public const string InfrastructureServices = "InfrastructureServices"; + public const string SerializableResourceType = "SerializableResourceType"; // Federation settings public const string AllowReutilizationOfComputeResources = "AllowReutilizationOfComputeResources"; @@ -764,8 +780,8 @@ public static class Properties public const string MsiUserAssignedType = "UserAssigned"; public const string MsiSystemAndUserAssignedType = "SystemAssigned,UserAssigned"; public const string DefaultIdentity = "defaultIdentity"; - public const string MsiDelegatedUserAssignedType = "DelegatedUserAssigned"; - public const string MsiDelegatedSystemAssignedType = "DelegatedSystemAssigned"; + public const string MsiDelegatedUserAssignedType = "DelegatedUserAssigned"; // only used for DefaultMsiProperties + public const string MsiDelegatedSystemAssignedType = "DelegatedSystemAssigned"; // only used for DefaultMsiProperties // ServiceDocument Resource public const string AddressesLink = "addresses"; @@ -857,6 +873,7 @@ public static class Properties public const string OfferLastReplaceTimestamp = "offerLastReplaceTimestamp"; public const string AutopilotSettings = "offerAutopilotSettings"; public const string IsOfferRestorePending = "isOfferRestorePending"; + public const int DefaultContainerCountForSharedThroughput = 25; public const string AutopilotTier = "tier"; public const string AutopilotTargetTier = "targetTier"; @@ -886,7 +903,18 @@ public static class Properties public const string EnableBurstCapacity = "enableBurstCapacity"; public const string EnableUserRateLimitingWithBursting = "enableUserRateLimitingWithBursting"; - public const string BlockOldSdkCallsForBurstCapacityEnabledAccount = "blockOldSdkCallsForBurstCapacityEnabledAccount"; + + // Priority Based Execution can be enabled by setting the naming config enablePriorityBasedThrottling to true + // When user sets EnablePriorityBasedExecution to true in an account PATCH request, enablePriorityBasedThrottling + // is set to true in the account configuration overrrides + public const string EnablePriorityBasedThrottling = "enablePriorityBasedThrottling"; + public const string EnablePriorityBasedExecution = "enablePriorityBasedExecution"; + public const string DefaultPriorityLevel = "defaultPriorityLevel"; + + // Global Rate Limiting + public const string EnableGlobalRateLimiting = "enableGlobalRateLimiting"; + // Cap the global budget for a partition. The value includes provisioned local budget. It cannot exceed 10K. + public const string GRLTargetUtilizationPerPartition = "GRLTargetUtilizationPerPartition"; public const string IsDryRun = "isDryRun"; @@ -929,6 +957,7 @@ public static class Properties public const string ThroughputFraction = "throughputFraction"; public const string PartitionKeyRangeStatus = "status"; public const string Parents = "parents"; + public const string Lsn = "lsn"; public const string NodeStatus = "NodeStatus"; public const string NodeName = "NodeName"; @@ -951,6 +980,9 @@ public static class Properties public const string EncryptionAlgorithm = "encryptionAlgorithm"; public const string ClientEncryptionPolicy = "clientEncryptionPolicy"; + public const string DataMaskingPolicy = "dataMaskingPolicy"; + public const string IsPolicyEnabled = "isPolicyEnabled"; + // ParitionKey Monitor public const string EnablePartitionKeyMonitor = "enablePartitionKeyMonitor"; @@ -1010,6 +1042,9 @@ public static class Properties public const string EnableLogstoreHeadStartSequenceVector = "enableLogStoreHeadStartSequenceVector"; public const string AllowSkippingOpLogFlushInRestore = "allowSkippingOpLogFlushInRestore"; + // Property to allow PITR disabling + public const string AllowPitrDisabling = "allowPITRDisabling"; + // Property to allow migration to analytical store public const string AllowCollectionMigrationToAnalyticalStore = "allowCollectionMigrationToAnalyticalStore"; public const string AllowMongoCollectionMigrationToAnalyticalStore = "allowMongoCollectionMigrationToAnalyticalStore"; @@ -1017,8 +1052,16 @@ public static class Properties // Property to enable storage analytics public const string EnableAnalyticalStorage = "enableAnalyticalStorage"; + // Properties related to Autoscale billing improvements. + public const string EnableAutoscaleThroughputUtilizationReporting = "enableAutoscaleThroughputUtilizationReporting"; // Configuration to report throughput utilization for autoscale billing. + public const string EnablePerRegionAutoscale = "enablePerRegionAutoscale"; //Configuration to enable PerRegion autoscale billing. + public const string EnableThroughputUtilizationPersistence = "enableThroughputUtilizationPersistence"; // configuration to enable throughput utlization persistance for server replica + public const string EnablePerRegionPerPartitionAutoscale = "enablePerRegionPerPartitionAutoscale"; // Property used in RP call to enable/disable the AutoscalePerRegion feature + public const string EnablePerRegionPerPartitionAutoscaleOptIn = "enablePerRegionPerPartitionAutoscaleOptIn"; // config override which will be used to determine if feature can be enabled or not + //properties to enable MaterializedViews public const string EnableMaterializedViews = "enableMaterializedViews"; //at DB account level. + public const string EnableOnlyColdStorageContainersInAccountV1 = "enableOnlyColdStorageContainersInAccountV1"; // property to enable full fidelity change feed (change feed with retention from remote+local storage). public const string EnableFullFidelityChangeFeed = "enableFullFidelityChangeFeed"; @@ -1031,7 +1074,7 @@ public static class Properties public const string ForceDisableFailover = "forceDisableFailover"; public const string EnableAutomaticFailover = "enableAutomaticFailover"; public const string SkipGracefulFailoverAttempt = "skipGracefulFailoverAttempt"; - public const string ForceUngracefulFailover = "forceUngracefulFailover"; + public const string ForceUngracefulFailover = "forceUngraceful"; // Location resource public const string IsEnabled = "isenabled"; @@ -1182,6 +1225,10 @@ public static class Properties // Customer Facing public const string IsVirtualNetworkFilterEnabled = "isVirtualNetworkFilterEnabled"; + // PerPartitionFailover Flags + // Likely Customer Facing + public const string EnablePerPartitionFailoverBehavior = "enablePerPartitionFailoverBehavior"; + // Backend public const string AccountVNETFilterEnabled = "accountVNETFilterEnabled"; public const string VirtualNetworkArmUrl = "virtualNetworkArmUrl"; @@ -1198,7 +1245,7 @@ public static class Properties public const string NspProfileProxyResources = "nspProfileProxyResources"; public const string NspAssociationProxyResource = "nspAssociationProxyResource"; public const string EnableNetworkSecurityPerimeter = "enableNetworkSecurityPerimeter"; - public const string EnableNetworkSecurityPerimeterOutbound = "enableNetworkSecurityPerimeterOutbound"; + public const string EnableConflictResolutionPolicyUpdate = "enableConflictResolutionPolicyUpdate"; // VNET/Subnet Resource(Network Resource Provider) public const string IgnoreMissingVNetServiceEndpoint = "ignoreMissingVNetServiceEndpoint"; @@ -1273,6 +1320,7 @@ public static class Properties // LogStore restore public const string IsRemoteStoreRestoreEnabled = "remoteStoreRestoreEnabled"; public const string RetentionPeriodInSeconds = "retentionPeriodInSeconds"; + public const string EnableRestoreTillEndOfLogChain = "enableRestoreTillEndOfLogChain"; // Remove stale backup blobs public const string BlobNamePrefix = "blobNamePrefix"; @@ -1287,6 +1335,7 @@ public static class Properties public const string RestrictDatabaseOfferContainerCount = "restrictDatabaseOfferContainerCount"; public const string MaxSharedOfferDatabaseCount = "maxSharedOfferDatabaseCount"; public const string MinRUsPerSharedThroughputCollection = "minRUsPerSharedThroughputCollection"; + public const string MaxContainersPerPartition = "maxContainersPerPartition"; // Conflict resolution policy public const string ConflictResolutionPolicy = "conflictResolutionPolicy"; @@ -1503,6 +1552,7 @@ public static class Properties // Mongo Properties public const string GlobalMongoProperties = "globalMongoProperties"; public const string ApiProperties = "apiProperties"; + public const string Disable16MBCapabilityChecks = "disable16MBCapabilityChecks"; // AAD Authentication public const string TrustedAadTenants = "trustedAadTenants"; @@ -1527,7 +1577,11 @@ public static class Properties public const string OldestRestorableTimeInUtc = "oldestRestorableTimeInUtc"; // Private endpoint map management + public const string Telemetry = "telemetry"; public const string DisabledTime = "disabledTime"; + public const string MapVersionBeforeCreation = "mapVersionBeforeCreation"; + public const string MapVersionBeforeDisabled = "mapVersionBeforeDisabled"; + public const string MapVersionBeforeDeletion = "mapVersionBeforeDeletion"; // SystemData public const string SystemData = "systemData"; @@ -1597,6 +1651,8 @@ public static class Properties // Purview-related properties public const string PurviewEnabled = "purviewEnabled"; + public const string AutoAuthPolicyFullPullScheduleIntervalInSeconds = "autoAuthPolicyFullPullScheduleIntervalInSeconds"; + public const int DefaultFullPullScheduleIntervalInSeconds = 7200; // TLS // New values for Self-Service Tls feature. @@ -1616,8 +1672,20 @@ public static class Properties public const string ClientTelemetryConfiguration = "clientTelemetryConfiguration"; public const string ClientTelemetryEnabled = "isEnabled"; public const string ClientTelemetryEndpoint = "endpoint"; + public const string ClientConfigApiRefreshIntervalInMinutes = "refreshIntervalInMinutes"; public const string EnableClientTelemetry = "enableClientTelemetry"; + // Throughput Pool Properties + public const string ThroughputPoolInstanceId = "throughputPoolInstanceId"; + public const string ThroughputPoolId = "throughputPoolId"; + public const string ThroughputPoolName = "throughputPoolName"; + public const string ThroughputPool = "throughputPool"; + public const string ThroughputPools = "throughputPools"; + public const string ThroughputPoolAccountLocation = "accountARMLocation"; + public const string ThroughputPoolAccountInstanceId = "accountInstanceId"; + public const string ThroughputPoolResourceUriTemplate = "subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.DocumentDB/throughputPools/{3}"; + public const string ThroughputPoolAccountUrl = "accountURI"; + public static class FederationOperations { public const string IsCapOperation = "isCapOperation"; @@ -1629,10 +1697,10 @@ public static class FederationCapActions public const string Cap = "Cap"; public const string Uncap = "Uncap"; } - + public static class InAccountUnDeleteNotAllowedReasons { - // Database UnDelete Failure + // Database UnDelete Failure public const string DatabaseLive = "Database already exists. Only deleted resources can be restored within same account."; public const string DatabaseWithSameNameLive = "Database with same name already exist as live database."; @@ -1675,6 +1743,7 @@ public static class SnapshotProperties public const string Keyspace = "keyspace"; public const string LSN = "lsn"; public const string IsMasterResourcesDeletionPending = "isMasterResourcesDeletionPending"; + public const string StorageAccountUris = "storageAccountUris"; } public static class RestoreMetadataResourceProperties @@ -1719,7 +1788,7 @@ public static class InternalIndexingProperties public static class InternalStoreProperties { public const string PropertyName = "internalStoreProperties"; - public const string AllowEnableLocalStoreCompression = "allowEnableLocalStoreCompression"; + public const string EnableBinaryEncodingOfContent = "enableBinaryEncodingOfContent"; } public static class TypeSystemPolicy @@ -1758,6 +1827,7 @@ public static class MsiProperties { public const string Type = "type"; public const string MsiIdentityUrl = "msiIdentityUrl"; + public const string InternalId = "internalId"; public const string ImplicitIdentity = "implicitIdentity"; public const string ExplicitIdentities = "explicitIdentities"; public const string DelegatedIdentities = "delegatedIdentities"; @@ -1955,6 +2025,9 @@ public static class KeyVaultProperties public const string KeyVaultKeyUriVersion = "keyVaultKeyUriVersion"; public const string DataEncryptionKeyStatus = "dataEncryptionKeyStatus"; public const string DataEncryptionKeyRequestOperation = "dataEncryptionKeyRequestOperation"; + public const string KeyVaultUnwrapErrorSubStatusCode = "keyVaultUnwrapErrorSubStatusCode"; + public const string KeyVaultUnwrapError = "keyVaultUnwrapError"; + public const string CustomerManagedKeyStatus = "customerManagedKeyStatus"; } public static class ManagedServiceIdentityProperties @@ -2022,6 +2095,12 @@ public static class SubscriptionsQuotaConstants public const int DefaultMaxRegionsPerGlobalDatabaseAccount = 50; } + public static class OperationProgressConstants + { + public const string IsProgressReportingSupported = "IsProgressReportingSupported"; + public const string ProgressPercentage = "ProgressPercentage"; + } + public static class PolicyConstants { public const string PolicyType = "policytype"; @@ -2115,6 +2194,12 @@ public static class ApiSpecificUrlNames public static string Table = "tables"; } + public static class MigratePartitionConstants + { + public static string SourceFederationId = "sourceFederationId"; + public static string SourceServiceName = "sourceServiceName"; + } + public static class MigratePartitionCallerSource { public static string Test = "Test"; @@ -2146,6 +2231,16 @@ public static class EnvironmentVariables public static class AvailabilityZoneMigrationProperties { public const string DesiredIsZoneRedundantValue = "desiredIsZoneRedundantValue"; + public const string MigrateServerPartitionsOnly = "migrateServerPartitionsOnly"; + public const string MasterSourceFederationId = "masterSourceFederationId"; + } + + public static class RoleNames + { + public const string MasterCluster0 = "MasterCluster0"; + public const string ServerCluster0 = "ServerCluster0"; + public const string FabricInfrastructure = "FabricInfrastructure"; + public const string CosmosDBGateway = "CosmosDBGateway"; } } } diff --git a/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs b/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs index 45b43e8ad6..d68f898b8c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/CustomTypeExtensions.cs @@ -35,7 +35,7 @@ internal static class CustomTypeExtensions #if COSMOSCLIENT public const string SDKName = "cosmos-netstandard-sdk"; - public const string SDKVersion = "3.31.5"; + public const string SDKVersion = "3.32.0"; #else public const string SDKName = "documentdb-netcore-sdk"; public const string SDKVersion = "2.14.0"; diff --git a/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs b/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs new file mode 100644 index 0000000000..4c62c6f623 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/DataMaskingIncludedPath.cs @@ -0,0 +1,21 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using Newtonsoft.Json; + + internal sealed class DataMaskingIncludedPath : JsonSerializable + { + /// + /// Gets or sets the path to be masked. Must be a top level path, eg. /salary + /// + [JsonProperty(PropertyName = Constants.Properties.Path)] + public string Path + { + get { return this.GetValue(Constants.Properties.Path); } + set { this.SetValue(Constants.Properties.Path, value); } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs new file mode 100644 index 0000000000..a783405067 --- /dev/null +++ b/Microsoft.Azure.Cosmos/src/direct/DataMaskingPolicy.cs @@ -0,0 +1,95 @@ +//------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------ + +namespace Microsoft.Azure.Documents +{ + using System; + using System.Collections.ObjectModel; + using System.Globalization; + using Newtonsoft.Json; + + /// + /// Represents the data masking policy for a collection in the Azure Cosmos DB service. + /// + /// + internal sealed class DataMaskingPolicy : JsonSerializable + { + private Collection includedPaths; + private Boolean isPolicyEnabled; + + /// + /// Initializes a new instance of the class for the Azure Cosmos DB service. + /// + public DataMaskingPolicy() + { + } + + /// + /// Paths of the item that need masked along with path-specific settings. + /// + [JsonProperty(PropertyName = Constants.Properties.IncludedPaths)] + public Collection IncludedPaths + { + get + { + if (this.includedPaths == null) + { + this.includedPaths = base.GetObjectCollection(Constants.Properties.IncludedPaths); + if (this.includedPaths == null) + { + this.includedPaths = new Collection(); + } + } + + return this.includedPaths; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IncludedPaths))); + } + + this.includedPaths = value; + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + } + } + + /// + /// Paths of the item that need masked along with path-specific settings. + /// + [JsonProperty(PropertyName = Constants.Properties.IsPolicyEnabled)] + public Boolean IsPolicyEnabled + { + get + { + if (!this.isPolicyEnabled) + { + this.isPolicyEnabled = base.GetValue(Constants.Properties.IsPolicyEnabled, true); + } + + return this.isPolicyEnabled; + } + set + { + if (!value) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(IsPolicyEnabled))); + } + + this.isPolicyEnabled = value; + base.SetValue(Constants.Properties.IsPolicyEnabled, this.IsPolicyEnabled); + } + } + + internal override void OnSave() + { + if (this.includedPaths != null) + { + base.SetObjectCollection(Constants.Properties.IncludedPaths, this.includedPaths); + base.SetValue(Constants.Properties.IsPolicyEnabled, this.isPolicyEnabled); + } + } + } +} diff --git a/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs b/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs index 6824830d73..b967f05545 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Dispatcher.cs @@ -336,6 +336,7 @@ public async Task CallAsync(ChannelCallArguments args, TransportR this.chaosInterceptor?.OnBeforeConnectionWrite(args); if (this.chaosInterceptor != null && this.chaosInterceptor.OnRequestCall(args, out StoreResponse faultyResponse)) { + transportRequestStats.RecordState(TransportRequestStats.RequestStage.Sent); return faultyResponse; } diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs index f3a84a8600..2adb2de13e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentCollection.cs @@ -113,10 +113,12 @@ class DocumentCollection : Resource private MaterializedViewDefinition materializedViewDefinition; private ByokConfig byokConfig; private ClientEncryptionPolicy clientEncryptionPolicy; + private DataMaskingPolicy dataMaskingPolicy; private Collection materializedViews; private EncryptionScopeMetadata encryptionScopeMetadata; private InAccountRestoreParameters restoreParameters; private byte uniqueIndexNameEncodingMode; + private Collection computedProperties; /// /// Initializes a new instance of the class for the Azure Cosmos DB service. @@ -154,6 +156,40 @@ public IndexingPolicy IndexingPolicy } } + /// + /// Gets or sets the collection containing objects in the container. + /// + /// + /// The collection containing objects associated with the container. + /// + [JsonProperty(PropertyName = Constants.Properties.ComputedProperties)] + internal Collection ComputedProperties + { + get + { + if (this.computedProperties == null) + { + this.computedProperties = base.GetValue>(Constants.Properties.ComputedProperties); + if (this.computedProperties == null) + { + this.computedProperties = new Collection(); + } + } + + return this.computedProperties; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "computedProperties")); + } + + this.computedProperties = value; + base.SetValue(Constants.Properties.ComputedProperties, this.computedProperties); + } + } + /// /// Gets the associated with the collection from the Azure Cosmos DB service. /// @@ -285,12 +321,10 @@ internal byte UniqueIndexNameEncodingMode } set { -#pragma warning disable CS0472 // The result of the expression is always the same since a value of this type is never equal to 'null' if(value == null) { throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, "UniqueIndexNameEncodingMode")); } -#pragma warning restore CS0472 // The result of the expression is always the same since a value of this type is never equal to 'null' this.uniqueIndexNameEncodingMode = value; this.SetValue(Constants.Properties.UniqueIndexNameEncodingMode, value); } @@ -919,6 +953,36 @@ internal ClientEncryptionPolicy ClientEncryptionPolicy } } + /// + /// Gets the associated with the collection from the Azure Cosmos DB service. + /// + /// + /// The DataMaskingPolicy associated with the collection. + /// + [JsonProperty(PropertyName = Constants.Properties.DataMaskingPolicy, DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] + internal DataMaskingPolicy DataMaskingPolicy + { + get + { + if (this.dataMaskingPolicy == null) + { + this.dataMaskingPolicy = base.GetObject(Constants.Properties.DataMaskingPolicy); + } + + return this.dataMaskingPolicy; + } + set + { + if (value == null) + { + throw new ArgumentNullException(string.Format(CultureInfo.CurrentCulture, RMResources.PropertyCannotBeNull, nameof(DataMaskingPolicy))); + } + + this.dataMaskingPolicy = value; + base.SetObject(Constants.Properties.DataMaskingPolicy, value); + } + } + /// /// Gets the materialized views on the collection. /// @@ -1004,6 +1068,11 @@ internal override void Validate() this.UniqueKeyPolicy.Validate(); this.ConflictResolutionPolicy.Validate(); this.UniqueIndexReIndexContext.Validate(); + + foreach (ComputedProperty computedProperty in this.ComputedProperties) + { + computedProperty.Validate(); + } } internal override void OnSave() @@ -1067,11 +1136,21 @@ internal override void OnSave() base.SetObject(Constants.Properties.ClientEncryptionPolicy, this.clientEncryptionPolicy); } + if (this.dataMaskingPolicy != null) + { + base.SetObject(Constants.Properties.DataMaskingPolicy, this.dataMaskingPolicy); + } + if (this.materializedViews != null) { base.SetValueCollection(Constants.Properties.MaterializedViews, this.materializedViews); } + if (this.computedProperties != null) + { + base.SetValueCollection(Constants.Properties.ComputedProperties, this.computedProperties); + } + if (this.restoreParameters != null) { base.SetObject(Constants.Properties.RestoreParams, this.restoreParameters); diff --git a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs index 86a4ab53b4..44ecfc7461 100644 --- a/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs +++ b/Microsoft.Azure.Cosmos/src/direct/DocumentServiceRequest.cs @@ -396,6 +396,76 @@ internal string ApiVersion } } + /// + /// StoreModel vs GatewayStoreModel contract for friends. + /// TODO: SDK V3 start using this contract. - https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2470799 + /// + internal static bool IsGatewayMode(ResourceType resourceType, OperationType operationType) + { + if (resourceType == ResourceType.Offer || + (resourceType.IsScript() && operationType != OperationType.ExecuteJavaScript) || + resourceType == ResourceType.PartitionKeyRange || + resourceType == ResourceType.Snapshot || + resourceType == ResourceType.ClientEncryptionKey || + (resourceType == ResourceType.PartitionKey && operationType == OperationType.Delete)) + { + return true; + } + + if (operationType == OperationType.Create + || operationType == OperationType.Upsert) + { + if (resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.Collection || + resourceType == ResourceType.Permission) + { + return true; + } + else + { + return false; + } + } + else if (operationType == OperationType.Delete) + { + if (resourceType == ResourceType.Database || + resourceType == ResourceType.User || + resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + else if ((operationType == OperationType.Replace) || (operationType == OperationType.CollectionTruncate)) + { + if (resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + else if (operationType == OperationType.Read) + { + if (resourceType == ResourceType.Collection) + { + return true; + } + else + { + return false; + } + } + + return false; + } + public bool ForceNameCacheRefresh { get; set; } /// @@ -473,6 +543,7 @@ public string HttpMethod case OperationType.BatchApply: case OperationType.Batch: case OperationType.QueryPlan: + case OperationType.MetadataCheckAccess: case OperationType.CompleteUserTransaction: return HttpConstants.HttpMethods.Post; @@ -534,12 +605,12 @@ public string HttpMethod case OperationType.ServiceReservation: case OperationType.GetSplitPoints: case OperationType.GetUnwrappedDek: + case OperationType.GetDekProperties: case OperationType.GetFederationConfigurations: case OperationType.GetDatabaseAccountConfigurations: case OperationType.GetStorageServiceConfigurations: case OperationType.ForcePartitionBackup: case OperationType.MasterInitiatedProgressCoordination: - case OperationType.MetadataCheckAccess: case OperationType.CreateSystemSnapshot: case OperationType.CreateRidRangeResources: case OperationType.GetAadGroups: @@ -684,6 +755,12 @@ public bool IsValidAddress(ResourceType resourceType = ResourceType.Unknown) { return true; } +#if !COSMOSCLIENT + else if (this.ResourceType == ResourceType.VectorClock) + { + return true; + } +#endif else { return false; diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs index 5eecfa246e..968e10fcaa 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRequestRetryPolicy.cs @@ -5,6 +5,7 @@ namespace Microsoft.Azure.Documents { using System; using System.Diagnostics; + using System.Globalization; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -17,6 +18,32 @@ namespace Microsoft.Azure.Documents internal sealed class GoneAndRetryWithRequestRetryPolicy : IRequestRetryPolicy where TResponse : IRetriableResponse { + struct ErrorOrResponse + { + private Exception exception; + private int statusCode; + + public ErrorOrResponse(Exception ex, TResponse response) + { + exception = ex; + this.statusCode = response != null ? (int)response.StatusCode : 0; + } + + public ErrorOrResponse(Exception ex) + { + exception = ex; + statusCode = 0; + } + + private string ExceptionToString() + { + // If no error code is set, use WithMessageAndData + return statusCode != 0 ? exception?.ToStringWithData() : exception?.ToStringWithMessageAndData(); + } + + public override string ToString() => exception != null ? this.ExceptionToString() : statusCode.ToString(CultureInfo.InvariantCulture); + } + private static readonly ThreadLocal Random = new ThreadLocal(() => new Random()); private const int defaultWaitTimeInMilliSeconds = 30000; @@ -133,8 +160,8 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp if (disableRetryWithPolicy) { DefaultTrace.TraceWarning( - "The GoneAndRetryWithRequestRetryPolicy is configured with disableRetryWithPolicy to true. Retries on 449(RetryWith) exceptions has been disabled. This is by design to allow users to handle the exception: {0}", - exception.ToStringWithMessageAndData()); + "The GoneAndRetryWithRequestRetryPolicy is configured with disableRetryWithPolicy to true. Retries on 449(RetryWith) exceptions has been disabled. This is by design to allow users to handle the exception: {0}", + new ErrorOrResponse(exception)); this.durationTimer.Stop(); shouldRetryResult = ShouldRetryResult.NoRetry(); return true; @@ -174,12 +201,16 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp DefaultTrace.TraceError( "{0} including at least one RetryWithException. " + "Will fail the request with RetryWithException. Exception: {1}. RetryWithException: {2}", - message, exception?.ToStringWithData() ?? response?.StatusCode.ToString(), this.lastRetryWithException.ToStringWithData()); + message, + new ErrorOrResponse(exception, response), + new ErrorOrResponse(this.lastRetryWithException)); exceptionToThrow = this.lastRetryWithException; } else { - DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, exception?.ToStringWithData() ?? response?.StatusCode.ToString()); + DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, + new ErrorOrResponse(exception, response)); + SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); if (exceptionSubStatus == SubStatusCodes.TimeoutGenerated410) { @@ -236,7 +267,8 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp } else { - DefaultTrace.TraceError("Received retry with exception after backoff/retry. Will fail the request. {0}", exception?.ToStringWithData() ?? response?.StatusCode.ToString()); + DefaultTrace.TraceError("Received retry with exception after backoff/retry. Will fail the request. {0}", new ErrorOrResponse(exception, response)); + exceptionToThrow = exception; } this.durationTimer.Stop(); @@ -306,7 +338,8 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp { // for third InvalidPartitionException, stop retrying. SubStatusCodes exceptionSubStatusCode = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); - DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", exception?.ToStringWithData() ?? response?.StatusCode.ToString()); + DefaultTrace.TraceCritical("Received second InvalidPartitionException after backoff/retry. Will fail the request. {0}", + new ErrorOrResponse(exception, response)); shouldRetryResult = ShouldRetryResult.NoRetry(ServiceUnavailableException.Create(exceptionSubStatusCode, innerException: exception)); return true; } @@ -317,7 +350,7 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp } else { - DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", exception?.ToStringWithData() ?? response?.StatusCode.ToString()); + DefaultTrace.TraceCritical("Received unexpected invalid collection exception, request should be non-null. {0}", new ErrorOrResponse(exception, response)); shouldRetryResult = ShouldRetryResult.NoRetry(new InternalServerErrorException(exception)); return true; } @@ -344,7 +377,7 @@ public bool TryHandleResponseSynchronously(DocumentServiceRequest request, TResp this.regionRerouteAttemptCount, backoffTime, timeout, - exception?.ToStringWithData() ?? response?.StatusCode.ToString()); + new ErrorOrResponse(exception, response)); shouldRetryResult = ShouldRetryResult.RetryAfter(backoffTime); this.previousException = exception; diff --git a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs index d7d4d971aa..f85a722255 100644 --- a/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs +++ b/Microsoft.Azure.Cosmos/src/direct/GoneAndRetryWithRetryPolicy.cs @@ -189,6 +189,8 @@ exception is PartitionKeyRangeGoneException || { DefaultTrace.TraceError("{0}. Will fail the request. {1}", message, exception.ToStringWithData()); SubStatusCodes exceptionSubStatus = DocumentClientException.GetExceptionSubStatusForGoneRetryPolicy(exception); + + if (this.detectConnectivityIssues && this.request.RequestContext.ClientRequestStatistics != null && this.request.RequestContext.ClientRequestStatistics.IsCpuHigh.GetValueOrDefault(false)) @@ -217,6 +219,7 @@ exception is PartitionKeyRangeGoneException || this.request.RequestContext.ClientRequestStatistics != null && this.request.RequestContext.ClientRequestStatistics.FailedReplicas.Count >= GoneAndRetryWithRetryPolicy.minFailedReplicaCountToConsiderConnectivityIssue) { + exceptionToThrow = new ServiceUnavailableException( string.Format( RMResources.ClientUnavailable, diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpConstants.cs b/Microsoft.Azure.Cosmos/src/direct/HttpConstants.cs index fa5ea1d4d1701ebd1dca74b60d0d6d656428d20f..7ea352df96cf1ba8b6c25cda63dd4d0362642ef6 100644 GIT binary patch delta 813 zcmZuvOK1~O6n(cH6G>tm(*%(SriuhV(-_l*pn}GVwOA6H2&I+M$(W>tB$iA?A}A^@ zT?8+9K}4!MMKm#s;19DGDp~1Ly0Z((!i^9=_syV3(yS=dzd=#Tj4gAiKFvSIt!A*_og5+$LFB3*OAHdMdursW#=)}?-5 zoO%kXHQrNG>Y(DOsjXN`tBu=WrXRw;^w9bt@Sy*+x=UkYvn)+cYL@jHBlk|* zH}a@;_cT8qf>)Puc6c8q4=B`egU78~z7-gxOzme7ps^gdHjFZ){GV1G+v9`u`5}za zy=m~!l@V|?yD#8QpG4a7@0&SlIXXx0W*`t)dosFRW|=wqF#|g!WW4#|HB2f$0S`jk AzyJUM delta 104 zcmbO;iG4#0`-TJ3lR46rHh+^|WxV-J00--28E>V@X9Bo3&k6Hrntb3I+vbX!Ut+c| zGG{DdpWG14vR%i4F^zG$K{X@C_GM0tTWY6INMMwjJ|T(GV7tvh#tlqxzQ*<=M;Iem E0M=nCGynhq diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpException.cs b/Microsoft.Azure.Cosmos/src/direct/HttpException.cs index c59d3051c3..9e7e4c82ee 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpException.cs @@ -86,7 +86,8 @@ internal DocumentClientException(string message, HttpResponseHeaders responseHeaders, HttpStatusCode? statusCode, Uri requestUri = null, - SubStatusCodes? substatusCode = null) + SubStatusCodes? substatusCode = null, + bool traceCallStack = true) : base(DocumentClientException.MessageWithActivityId(message, responseHeaders), innerException) { this.responseHeaders = new StoreResponseNameValueCollection(); @@ -127,7 +128,8 @@ internal DocumentClientException(string message, "DocumentClientException with status code {0}, message: {1}, inner exception: {2}, and response headers: {3}", this.StatusCode ?? 0, message, - innerException != null ? innerException.ToString() : "null", + innerException != null ? + (traceCallStack ? innerException.ToString() : innerException.ToStringWithMessageAndData()) : "null", SerializeHTTPResponseHeaders(responseHeaders)); } } @@ -220,6 +222,13 @@ internal DocumentClientException(SerializationInfo info, StreamingContext contex info.ToString()); } } + + internal DocumentClientException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + this.LSN = -1; + this.PartitionKeyRangeId = null; + } #endif /// diff --git a/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs b/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs index 6d8e7bdcb0..25419952ef 100644 --- a/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/HttpTransportClient.cs @@ -380,6 +380,16 @@ private HttpRequestMessage PrepareHttpMessage( HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.PopulateCapacityType, request.Headers[WFConstants.BackendHeaders.PopulateCapacityType]); } + if (request.Headers[WFConstants.BackendHeaders.ClientIpAddress] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.ClientIpAddress, request.Headers[WFConstants.BackendHeaders.ClientIpAddress]); + } + + if (request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized] != null) + { + HttpTransportClient.AddHeader(httpRequestMessage.Headers, WFConstants.BackendHeaders.IsRequestNotAuthorized, request.Headers[WFConstants.BackendHeaders.IsRequestNotAuthorized]); + } + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsAutoScaleRequest, request); //Query @@ -478,6 +488,8 @@ private HttpRequestMessage PrepareHttpMessage( HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.IsMigratedFixedCollection, request); HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.SetMasterResourcesDeletionPending, request); HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.HighPriorityForcedBackup, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, request); + HttpTransportClient.AddHeader(httpRequestMessage.Headers, HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, request); Stream clonedStream = null; if (request.Body != null) @@ -616,6 +628,13 @@ private HttpRequestMessage PrepareHttpMessage( httpRequestMessage.Content = new StreamContent(clonedStream); break; + case OperationType.GetDekProperties: + httpRequestMessage.RequestUri = physicalAddress; + httpRequestMessage.Method = HttpMethod.Post; + Debug.Assert(clonedStream != null); + httpRequestMessage.Content = new StreamContent(clonedStream); + break; + case OperationType.ReadReplicaFromMasterPartition: case OperationType.ReadReplicaFromServerPartition: httpRequestMessage.RequestUri = physicalAddress; @@ -635,6 +654,8 @@ private HttpRequestMessage PrepareHttpMessage( case OperationType.BatchReportThroughputUtilization: case OperationType.ControllerBatchReportCharges: case OperationType.ControllerBatchGetOutput: + case OperationType.ControllerBatchAutoscaleRUsConsumption: + case OperationType.ControllerBatchGetAutoscaleAggregateOutput: httpRequestMessage.RequestUri = HttpTransportClient.GetRootOperationUri(physicalAddress, resourceOperation.operationType); httpRequestMessage.Method = HttpMethod.Post; Debug.Assert(clonedStream != null); diff --git a/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs b/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs index ca302839c0..7359b0e856 100644 --- a/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs +++ b/Microsoft.Azure.Cosmos/src/direct/IClientSideRequestStatistics.cs @@ -12,9 +12,9 @@ internal interface IClientSideRequestStatistics { List ContactedReplicas { get; set; } - HashSet FailedReplicas { get; } + HashSet FailedReplicas { get;} - HashSet<(string, Uri)> RegionsContacted { get; } + HashSet<(string, Uri)> RegionsContacted { get;} bool? IsCpuHigh { get; } @@ -53,4 +53,5 @@ void RecordHttpException(HttpRequestMessage request, ResourceType resourceType, DateTime requestStartTimeUtc); } -} \ No newline at end of file +} + diff --git a/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs b/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs index cee6bb8c83..199261cc91 100644 --- a/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/InAccountRestoreParameters.cs @@ -67,6 +67,19 @@ public string SourceBackupLocation set { base.SetValue(Constants.Properties.SourceBackupLocation, value); } } + /// + /// Gets or sets the for triggering the InAccount Restore as part of RestoreParameters + /// + /// + /// A valid value should be true or false + /// + [JsonProperty(PropertyName = Constants.Properties.RestoreWithTTLDisabled)] + public bool RestoreWithTTLDisabled + { + get { return base.GetValue(Constants.Properties.RestoreWithTTLDisabled); } + set { base.SetValue(Constants.Properties.RestoreWithTTLDisabled, value); } + } + internal override void Validate() { base.Validate(); diff --git a/Microsoft.Azure.Cosmos/src/direct/Int128.cs b/Microsoft.Azure.Cosmos/src/direct/Int128.cs index 3aed0d88fa..2c4894fbb9 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Int128.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Int128.cs @@ -74,6 +74,25 @@ public Int128(byte[] data) return left.value < right.value; } + public static bool operator ==(Int128 left, Int128 right) + { + return left.value == right.value; + } + + public static bool operator !=(Int128 left, Int128 right) + { + return left.value != right.value; + } + public override int GetHashCode() + { + return value.GetHashCode(); + } + + public override bool Equals(object obj) + { + return obj is Int128 other && this.Equals(other); + } + public byte[] Bytes { get diff --git a/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs b/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs index 321215d199..d1a90e6759 100644 --- a/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs +++ b/Microsoft.Azure.Cosmos/src/direct/JSonSerializable.cs @@ -821,6 +821,11 @@ internal Dictionary GetObjectDictionary( if (token != null) { Dictionary jobjectDictionary = token.ToObject>(); + if (jobjectDictionary == null) + { + return null; + } + Dictionary objectDictionary = new Dictionary(); foreach (KeyValuePair kvp in jobjectDictionary) { diff --git a/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs b/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs index 3ba0499ba5..20103cc8e3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LinuxSystemUtilizationReader.cs @@ -237,6 +237,8 @@ public ProcMemInfoFileParser() : this(DefaultProcMemInfoFilePath) /// /// Allows customization of the proc stat file path to allow testing this on Non-Linux machines /// + /// + /// internal ProcMemInfoFileParser(string procMemInfoFilePath) { if (String.IsNullOrWhiteSpace(procMemInfoFilePath)) diff --git a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs index cf4d749424..6a5664eb01 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LoadBalancingPartition.cs @@ -36,13 +36,13 @@ internal sealed class LoadBalancingPartition : IDisposable // This channel factory delegate is meant for unit testing only and a default implementation is provided. // However it can be extended to support the main line code path if needed. - private readonly Func, IChannel> channelFactory; + private readonly Func, IChannel> channelFactory; public LoadBalancingPartition( Uri serverUri, ChannelProperties channelProperties, bool localRegionRequest, - Func, IChannel> channelFactory = null, + Func, IChannel> channelFactory = null, IChaosInterceptor chaosInterceptor = null) { Debug.Assert(serverUri != null); @@ -188,8 +188,9 @@ public async Task RequestAsync( channelsCreated = targetChannels - this.openChannels.Count; } - Action onChannelOpen = - (Guid createId, Uri serverUri, Channel createdChannel) => this.chaosInterceptor?.OnChannelOpen(createId, serverUri, request, createdChannel); + Action onChannelOpen = + (Guid createId, Guid connectionCorrelationId, Uri serverUri, Channel createdChannel) + => this.chaosInterceptor?.OnChannelOpen(createId, serverUri, request, createdChannel); while (this.openChannels.Count < targetChannels) { @@ -317,7 +318,7 @@ public void Dispose() /// An instance of . private IChannel OpenChannelAndIncrementCapacity( Guid activityId, - Action onChannelOpen = null) + Action onChannelOpen = null) { Debug.Assert(this.capacityLock.IsWriteLockHeld); @@ -364,7 +365,7 @@ private static IChannel CreateAndInitializeChannel( bool localRegionRequest, SemaphoreSlim concurrentOpeningChannelSlim, IChaosInterceptor chaosInterceptor = null, - Action onChannelOpen = null) + Action onChannelOpen = null) { return new Channel( activityId, diff --git a/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs b/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs index f83fd22c37..c2258d7493 100644 --- a/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs +++ b/Microsoft.Azure.Cosmos/src/direct/LocationNames.cs @@ -377,6 +377,38 @@ static class LocationNames /// /// Name of the Azure Mexico Central region in the Azure Cosmos DB service. /// - internal const string MexicoCentral = "Mexico Central"; + public const string MexicoCentral = "Mexico Central"; + + /// + /// Name of the Azure Spain Central region in the Azure Cosmos DB service. + /// + public const string SpainCentral = "Spain Central"; + + /// + /// Name of the Azure Taiwan North region in the Azure Cosmos DB service. + /// + internal const string TaiwanNorth = "Taiwan North"; + + /// + /// Name of the Azure Taiwan Northwest region in the Azure Cosmos DB service. + /// + internal const string TaiwanNorthwest = "Taiwan Northwest"; + + /// + /// Name of the Azure Austria East region in the Azure Cosmos DB service. + /// + internal const string AustriaEast = "Austria East"; + + /// + /// Name of the Azure New Zealand North region in the Azure Cosmos DB service. + /// + internal const string NewZealandNorth = "New Zealand North"; } -} \ No newline at end of file +} + + + + + + + diff --git a/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs b/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs index 7eadfeba21..c7b493cdee 100644 --- a/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/NotFoundException.cs @@ -36,14 +36,14 @@ public NotFoundException(string message, Exception innerException) } - public NotFoundException(Exception innerException) - : this(RMResources.NotFound, innerException, null) + public NotFoundException(Exception innerException, bool traceCallStack = true) + : this(RMResources.NotFound, innerException, null, traceCallStack: traceCallStack) { } - public NotFoundException(Exception innerException, SubStatusCodes subStatusCode) - : this(RMResources.NotFound, innerException, headers: null, subStatusCode: subStatusCode) + public NotFoundException(Exception innerException, SubStatusCodes subStatusCode, bool traceCallStack = true) + : this(RMResources.NotFound, innerException, headers: null, subStatusCode: subStatusCode, traceCallStack: traceCallStack) { } @@ -53,8 +53,8 @@ public NotFoundException(string message, INameValueCollection headers, Uri reque SetDescription(); } - public NotFoundException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null) - : base(message, innerException, headers, HttpStatusCode.NotFound, requestUri, subStatusCode) + public NotFoundException(string message, Exception innerException, HttpResponseHeaders headers, Uri requestUri = null, SubStatusCodes? subStatusCode = null, bool traceCallStack = true) + : base(message, innerException, headers, HttpStatusCode.NotFound, requestUri, subStatusCode, traceCallStack) { SetDescription(); } diff --git a/Microsoft.Azure.Cosmos/src/direct/OperationType.cs b/Microsoft.Azure.Cosmos/src/direct/OperationType.cs index fb4fedfff4..65848b4c88 100644 --- a/Microsoft.Azure.Cosmos/src/direct/OperationType.cs +++ b/Microsoft.Azure.Cosmos/src/direct/OperationType.cs @@ -114,13 +114,13 @@ internal enum OperationType // These names make it unclear what they map to in RequestOperationType. ExecuteJavaScript = -2, + GetConfiguration = -8, #if !COSMOSCLIENT ForceConfigRefresh = -3, ReportThroughputUtilization = -4, ServiceReservation = -5, ControllerBatchReportCharges = -6, ControllerBatchGetOutput = -7, - GetConfiguration = -8, GetStorageAccountKey = -9, GetFederationConfigurations = -10, GetDatabaseAccountConfigurations = -11, @@ -135,6 +135,9 @@ internal enum OperationType GetCustomerManagedKeyStatus = -20, GetBatchCustomerManagedKeyStatus = -21, XPDatabaseAccountMetaData = -22, + ControllerBatchAutoscaleRUsConsumption = -23, + ControllerBatchGetAutoscaleAggregateOutput = -24, + GetDekProperties = -25, #endif } @@ -218,10 +221,10 @@ public static bool IsReadOperation(this OperationType type) type == OperationType.SqlQuery || type == OperationType.Head || type == OperationType.HeadFeed || + type == OperationType.MetadataCheckAccess || type == OperationType.QueryPlan #if !COSMOSCLIENT || - type == OperationType.MetadataCheckAccess || type == OperationType.GetStorageAuthToken #endif ; diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs index ce5ae5a0eb..daa3cd144b 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyInternal.cs @@ -720,75 +720,20 @@ public static string ToHex(byte[] bytes, int start, int length) return new string(result); } } + + public static string GetMiddleRangeEffectivePartitionKey(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) => partitionKeyDefinition.Kind switch + { + PartitionKind.Hash => GetMiddleRangeEffectivePartitionKeyForHash(minInclusive, maxExclusive, partitionKeyDefinition), + PartitionKind.MultiHash => GetMiddleRangeEffectivePartitionKeyForMultiHash(minInclusive, maxExclusive, partitionKeyDefinition), + _ => throw new InternalServerErrorException($"Unexpected PartitionKey Kind {partitionKeyDefinition.Kind}. Can determine middle of range only for hash and multihash partitioning.") + }; - public static string GetMiddleRangeEffectivePartitionKey(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + private static string GetMiddleRangeEffectivePartitionKeyForHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) { - switch (partitionKeyDefinition.Kind) + switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) { - case PartitionKind.Hash: - { - switch (partitionKeyDefinition.Version ?? PartitionKeyDefinitionVersion.V1) - { - case PartitionKeyDefinitionVersion.V2: - { - Int128 min = 0; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] minBytes = PartitionKeyInternal.HexStringToByteArray(minInclusive); - Array.Reverse(minBytes); - min = new Int128(minBytes); - } - - Int128 max = MaxHashV2Value; - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { - byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(maxExclusive); - Array.Reverse(maxBytes); - max = new Int128(maxBytes); - } - - byte[] midBytes = (min + (max - min) / 2).Bytes; - Array.Reverse(midBytes); - return HexConvert.ToHex(midBytes, 0, midBytes.Length); - } - case PartitionKeyDefinitionVersion.V1: - { - long min = 0; - long max = uint.MaxValue; - if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) - { -#pragma warning disable 0612 - max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; -#pragma warning restore 0612 - } - - return ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent((min + max) / 2) }); - } - - default: - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); - } - } - - case PartitionKind.MultiHash: + case PartitionKeyDefinitionVersion.V2: { - if (partitionKeyDefinition.Version == PartitionKeyDefinitionVersion.V1) - { - throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion " + partitionKeyDefinition.Version + " for MultiHash Partition kind"); - } - - //Extract only the first EPK from a multi-path partition key. - //[Given this is invoked for equal range Split, we do not want to split a subrange of a top-level key] - minInclusive = minInclusive.Substring(0, Math.Min(minInclusive.Length, HashV2EPKLength)); - maxExclusive = maxExclusive.Substring(0, Math.Min(maxExclusive.Length, HashV2EPKLength)); - Int128 min = 0; if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) { @@ -809,10 +754,115 @@ public static string GetMiddleRangeEffectivePartitionKey(string minInclusive, st Array.Reverse(midBytes); return HexConvert.ToHex(midBytes, 0, midBytes.Length); } + case PartitionKeyDefinitionVersion.V1: + { + long min = 0; + long max = uint.MaxValue; + if (!minInclusive.Equals(MinimumInclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + min = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(minInclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + if (!maxExclusive.Equals(MaximumExclusiveEffectivePartitionKey, StringComparison.Ordinal)) + { +#pragma warning disable 0612 + max = (long)((NumberPartitionKeyComponent)FromHexEncodedBinaryString(maxExclusive).Components[0]).Value; +#pragma warning restore 0612 + } + + return ToHexEncodedBinaryString(new[] { new NumberPartitionKeyComponent((min + max) / 2) }); + } default: - throw new InternalServerErrorException("Unexpected PartitionKey Kind. Can determine middle of range only for hash and multihash partitioning."); + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion"); + } + } + + private static IReadOnlyList GetHashValueFromEPKForMultiHash(string epkValueString, PartitionKeyDefinition partitionKeyDefinition) + { + IList hashes = new List(); + int pathCountInEPK = (epkValueString.Length + (HashV2EPKLength - 1))/HashV2EPKLength; + + for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) + { + if (index < pathCountInEPK) + { + int startIndexForEPK = index * HashV2EPKLength; //Offset it by the length of previously read EPK(s), + + // All EPK value lengths are HashV2EPKLength, however the end EPK value is 'FF' + // FF is a special marker which appears only as a suffix + if (epkValueString.Length - startIndexForEPK < HashV2EPKLength) + { + hashes.Add(MaxHashV2Value); + } + else + { + // Extract the EPK for nth key + string epkSubPart = epkValueString.Substring(startIndexForEPK, HashV2EPKLength); + byte[] maxBytes = PartitionKeyInternal.HexStringToByteArray(epkSubPart); + Array.Reverse(maxBytes); + hashes.Add(new Int128(maxBytes)); + } + } + else // The EPK has less values than Paths.Count in the PkDef, this is empty partitionkey. + { + hashes.Add(0); + } + } + + return (IReadOnlyList)hashes; + } + + //Refer docs/design/elasticity/SubpartitioningContainerSplit.md for implementation detail + private static string GetMiddleRangeEffectivePartitionKeyForMultiHash(string minInclusive, string maxExclusive, PartitionKeyDefinition partitionKeyDefinition) + { + if (partitionKeyDefinition.Version == PartitionKeyDefinitionVersion.V1) + { + throw new InternalServerErrorException("Unexpected PartitionKeyDefinitionVersion " + partitionKeyDefinition.Version + " for MultiHash Partition kind"); + } + + IReadOnlyList minInclusiveHashValues = GetHashValueFromEPKForMultiHash(minInclusive, partitionKeyDefinition); + IReadOnlyList maxExclusiveHashValues = GetHashValueFromEPKForMultiHash(maxExclusive, partitionKeyDefinition); + IList midPointHashValues = new List(partitionKeyDefinition.Paths.Count); + + for (int index = 0; index < partitionKeyDefinition.Paths.Count; index++) + { + Int128 min = minInclusiveHashValues[index]; + Int128 max = maxExclusiveHashValues[index]; + + if (min == max || min + 1 == max) + { + midPointHashValues.Add(min); + } + else + { + /* It is possible, for Example if MinEPK, MaxEPK are [20, 40], [21, 10] respectively, + * the nMinEPKCurrentSubRange = 40 and nMaxEPKCurrentSubRange = 10 + * Since in the above step we are already setting 20 to be first level midPoint, + * for a valid second level midPoint we must look for it the range [40, HashV2Max] + */ + if (min > max) + { + max = MaxHashV2Value; + } + + Int128 midValue = (min + (max - min) / 2); + midPointHashValues.Add(midValue); + break; + } } + + StringBuilder midPointEPKBuilder = new StringBuilder() ; + foreach (Int128 value in midPointHashValues) + { + byte[] midBytes = value.Bytes; + Array.Reverse(midBytes); + midPointEPKBuilder.Append(HexConvert.ToHex(midBytes, 0, midBytes.Length)); + } + + return midPointEPKBuilder.ToString(); } public static string[] GetNEqualRangeEffectivePartitionKeys( diff --git a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs index 122837d1e1..17f3829476 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PartitionKeyRange.cs @@ -95,6 +95,19 @@ internal PartitionKeyRangeStatus Status } } + [JsonProperty(PropertyName = Constants.Properties.Lsn)] + public long LSN + { + get + { + return base.GetValue(Constants.Properties.Lsn); + } + set + { + base.SetValue(Constants.Properties.Lsn, value); + } + } + /// /// Contains ids or parent ranges in the Azure Cosmos DB service. /// For example if range with id '1' splits into '2' and '3', diff --git a/Microsoft.Azure.Cosmos/src/direct/Paths.cs b/Microsoft.Azure.Cosmos/src/direct/Paths.cs index 92ba936786..ef077ac631 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Paths.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Paths.cs @@ -26,6 +26,7 @@ internal static class Paths public const string Operations_GetStorageAccountKey = "getstorageaccountkey"; public const string Operations_GetStorageAccountSas = "getstorageaccountsas"; public const string Operations_GetUnwrappedDek = "getunwrappeddek"; + public const string Operations_GetDekProperties = "getdekproperties"; public const string Operations_GetCustomerManagedKeyStatus = "getcustomermanagedkeystatus"; public const string Operations_ReadReplicaFromMasterPartition = "readreplicafrommasterpartition"; public const string Operations_ReadReplicaFromServerPartition = "readreplicafromserverpartition"; @@ -308,6 +309,8 @@ internal static class Paths // controller service public const string ControllerOperations_BatchGetOutput = "controllerbatchgetoutput"; public const string ControllerOperations_BatchReportCharges = "controllerbatchreportcharges"; + public const string ControllerOperations_BatchAutoscaleRUsConsumption = "controllerbatchautoscalerusconsumption"; + public const string ControllerOperations_BatchGetAutoscaleAggregateOutput = "controllerbatchgetautoscaleaggregateoutput"; // vector clock public const string VectorClockPathSegment = "vectorclock"; diff --git a/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs b/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs index 02c3c758c5..c1783aa89e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PathsHelper.cs @@ -1289,6 +1289,10 @@ public static string GeneratePath(ResourceType resourceType, string ownerOrResou { return Paths.DatabaseAccountSegment; } + else if (resourceType == ResourceType.DatabaseAccount && operationType == OperationType.MetadataCheckAccess) + { + return Paths.OperationsPathSegment + "/" + Paths.Operations_MetadataCheckAccess; + } else if (resourceType == ResourceType.DatabaseAccount) { return Paths.DatabaseAccountSegment + "/" + ownerOrResourceId; @@ -1447,6 +1451,10 @@ public static string GenerateRootOperationPath(OperationType operationType) return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetOutput; case OperationType.ControllerBatchReportCharges: return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchReportCharges; + case OperationType.ControllerBatchAutoscaleRUsConsumption: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchAutoscaleRUsConsumption; + case OperationType.ControllerBatchGetAutoscaleAggregateOutput: + return Paths.OperationsPathSegment + "/" + Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput; case OperationType.GetConfiguration: return Paths.OperationsPathSegment + "/" + Paths.Operations_GetConfiguration; case OperationType.GetFederationConfigurations: @@ -1465,6 +1473,8 @@ public static string GenerateRootOperationPath(OperationType operationType) return Paths.OperationsPathSegment + "/" + Paths.Operations_GetStorageAccountSas; case OperationType.GetUnwrappedDek: return Paths.OperationsPathSegment + "/" + Paths.Operations_GetUnwrappedDek; + case OperationType.GetDekProperties: + return Paths.OperationsPathSegment + "/" + Paths.Operations_GetDekProperties; case OperationType.GetCustomerManagedKeyStatus: return Paths.OperationsPathSegment + "/" + Paths.Operations_GetCustomerManagedKeyStatus; case OperationType.ReadReplicaFromMasterPartition: @@ -1556,6 +1566,8 @@ private static bool IsRootOperation(in StringSegment operationSegment, in String operationTypeSegment.Equals(Paths.ReplicaOperations_BatchReportThroughputUtilization, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetOutput, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.ControllerOperations_BatchReportCharges, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchAutoscaleRUsConsumption, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.ControllerOperations_BatchGetAutoscaleAggregateOutput, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_GetFederationConfigurations, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_GetStorageServiceConfigurations, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_GetConfiguration, StringComparison.OrdinalIgnoreCase) || @@ -1564,11 +1576,13 @@ private static bool IsRootOperation(in StringSegment operationSegment, in String operationTypeSegment.Equals(Paths.Operations_GetDatabaseAccountConfigurations, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_XPDatabaseAccountMetaData, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_GetUnwrappedDek, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_GetDekProperties, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_GetCustomerManagedKeyStatus, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromMasterPartition, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_ReadReplicaFromServerPartition, StringComparison.OrdinalIgnoreCase) || operationTypeSegment.Equals(Paths.Operations_MasterInitiatedProgressCoordination, StringComparison.OrdinalIgnoreCase) || - operationTypeSegment.Equals(Paths.Operations_GetAadGroups, StringComparison.OrdinalIgnoreCase); + operationTypeSegment.Equals(Paths.Operations_GetAadGroups, StringComparison.OrdinalIgnoreCase) || + operationTypeSegment.Equals(Paths.Operations_MetadataCheckAccess, StringComparison.OrdinalIgnoreCase); } private static bool IsTopLevelOperationOperation(in StringSegment replicaSegment, in StringSegment addressSegment) diff --git a/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs b/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs index d2f409bc3b..77d894adad 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerfCounters.cs @@ -27,8 +27,6 @@ internal sealed class PerfCounters : IDisposable private PerformanceCounter currentFrontendConnections; - private PerformanceCounter fabricResolveServiceFailures; - private PerformanceCounter queryRequestsPerSec; private PerformanceCounter triggerRequestsPerSec; @@ -47,10 +45,6 @@ internal sealed class PerfCounters : IDisposable private PerformanceCounter backendConnectionOpenAverageLatencyBase; - private PerformanceCounter fabricResolveServiceAverageLatency; - - private PerformanceCounter fabricResolveServiceAverageLatencyBase; - private PerformanceCounter routingFailures; private PerformanceCounter backendConnectionOpenFailuresDueToSynRetransmitPerSecond; @@ -119,14 +113,6 @@ public PerformanceCounter CurrentFrontendConnections } } - public PerformanceCounter FabricResolveServiceFailures - { - get - { - return this.fabricResolveServiceFailures; - } - } - public PerformanceCounter QueryRequestsPerSec { get @@ -199,22 +185,6 @@ public PerformanceCounter BackendConnectionOpenAverageLatencyBase } } - public PerformanceCounter FabricResolveServiceAverageLatency - { - get - { - return this.fabricResolveServiceAverageLatency; - } - } - - public PerformanceCounter FabricResolveServiceAverageLatencyBase - { - get - { - return this.fabricResolveServiceAverageLatencyBase; - } - } - public PerformanceCounter RoutingFailures { get @@ -370,9 +340,6 @@ public void InitializePerfCounters() this.currentFrontendConnections = new PerformanceCounter(this.performanceCategory, "Current Frontend Connections", false); this.currentFrontendConnections.RawValue = 0; - this.fabricResolveServiceFailures = new PerformanceCounter(this.performanceCategory, "Fabric Resolve Service Failures", false); - this.fabricResolveServiceFailures.RawValue = 0; - this.queryRequestsPerSec = new PerformanceCounter(this.performanceCategory, "Query Requests/sec", false); this.queryRequestsPerSec.RawValue = 0; @@ -400,12 +367,6 @@ public void InitializePerfCounters() this.backendConnectionOpenAverageLatencyBase = new PerformanceCounter(this.performanceCategory, "Backend Connection Open Average Latency Base", false); this.backendConnectionOpenAverageLatencyBase.RawValue = 0; - this.fabricResolveServiceAverageLatency = new PerformanceCounter(this.performanceCategory, "Fabric Resolve Service Average Latency", false); - this.fabricResolveServiceAverageLatency.RawValue = 0; - - this.fabricResolveServiceAverageLatencyBase = new PerformanceCounter(this.performanceCategory, "Fabric Resolve Service Average Latency Base", false); - this.fabricResolveServiceAverageLatencyBase.RawValue = 0; - this.routingFailures = new PerformanceCounter(this.performanceCategory, "Routing Failures", false); this.routingFailures.RawValue = 0; @@ -432,8 +393,6 @@ public void Dispose() using (this.currentFrontendConnections) { } - using (this.fabricResolveServiceFailures) { } - using (this.queryRequestsPerSec) { } using (this.triggerRequestsPerSec) { } @@ -452,10 +411,6 @@ public void Dispose() using (this.backendConnectionOpenAverageLatencyBase) { } - using (this.fabricResolveServiceAverageLatency) { } - - using (this.fabricResolveServiceAverageLatencyBase) { } - using (this.routingFailures) { } using (this.backendConnectionOpenFailuresDueToSynRetransmitPerSecond) { } diff --git a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs index 6214467483..59ad2c2b0c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PerformanceActivities.cs @@ -3,13 +3,6 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Documents { - internal sealed class ResolveFabricPerformanceActivity : PerformanceActivity - { - public ResolveFabricPerformanceActivity() - : base(null, null, PerfCounters.Counters.FabricResolveServiceFailures, PerfCounters.Counters.FabricResolveServiceAverageLatency, PerfCounters.Counters.FabricResolveServiceAverageLatencyBase, "ResolveFabric") - { } - } - internal sealed class OpenConnectionPerformanceActivity : PerformanceActivity { public OpenConnectionPerformanceActivity() diff --git a/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs b/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs index f6e81d5844..96273c0302 100644 --- a/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs +++ b/Microsoft.Azure.Cosmos/src/direct/PreconditionFailedException.cs @@ -8,6 +8,7 @@ namespace Microsoft.Azure.Documents using System.Net.Http.Headers; using System.Runtime.Serialization; using Microsoft.Azure.Documents.Collections; + using Newtonsoft.Json; [Serializable] internal sealed class PreconditionFailedException : DocumentClientException @@ -60,6 +61,7 @@ public PreconditionFailedException( } #if !NETSTANDARD16 + [JsonConstructor] private PreconditionFailedException(SerializationInfo info, StreamingContext context) : base(info, context, HttpStatusCode.PreconditionFailed) { diff --git a/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs b/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs index 76ade3e8e1..7bfb3d9b4e 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RegionProximityUtil.cs @@ -104,6 +104,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 2 }, { LocationNames.AustraliaEast, 6 }, { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, { LocationNames.BrazilSouth, 314 }, { LocationNames.BrazilSoutheast, 314 }, { LocationNames.CanadaCentral, 204 }, @@ -122,9 +123,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 242 }, { LocationNames.FranceSouth, 230 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 254 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 246 }, { LocationNames.IsraelCentral, 168 }, { LocationNames.ItalyNorth, 240 }, @@ -136,6 +135,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 148 }, { LocationNames.MalaysiaSouth, 94 }, { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 100 }, { LocationNames.NorthCentralUS, 192 }, { LocationNames.NorthEurope, 262 }, { LocationNames.NorwayEast, 272 }, @@ -147,10 +147,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 174 }, { LocationNames.SoutheastAsia, 94 }, { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 242 }, { LocationNames.SwedenCentral, 272 }, { LocationNames.SwedenSouth, 272 }, { LocationNames.SwitzerlandNorth, 240 }, { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, { LocationNames.UAECentral, 168 }, { LocationNames.UAENorth, 168 }, { LocationNames.UKSouth, 250 }, @@ -183,6 +186,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 0 }, { LocationNames.AustraliaEast, 6 }, { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, { LocationNames.BrazilSouth, 313 }, { LocationNames.BrazilSoutheast, 313 }, { LocationNames.CanadaCentral, 204 }, @@ -201,9 +205,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 242 }, { LocationNames.FranceSouth, 230 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 256 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 246 }, { LocationNames.IsraelCentral, 168 }, { LocationNames.ItalyNorth, 240 }, @@ -215,6 +217,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 148 }, { LocationNames.MalaysiaSouth, 92 }, { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 2 }, { LocationNames.NorthCentralUS, 192 }, { LocationNames.NorthEurope, 262 }, { LocationNames.NorwayEast, 272 }, @@ -226,10 +229,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 174 }, { LocationNames.SoutheastAsia, 92 }, { LocationNames.SouthIndia, 124 }, + { LocationNames.SpainCentral, 242 }, { LocationNames.SwedenCentral, 272 }, { LocationNames.SwedenSouth, 272 }, { LocationNames.SwitzerlandNorth, 240 }, { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, { LocationNames.UAECentral, 168 }, { LocationNames.UAENorth, 168 }, { LocationNames.UKSouth, 248 }, @@ -262,6 +268,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 6 }, { LocationNames.AustraliaEast, 0 }, { LocationNames.AustraliaSoutheast, 14 }, + { LocationNames.AustriaEast, 236 }, { LocationNames.BrazilSouth, 308 }, { LocationNames.BrazilSoutheast, 308 }, { LocationNames.CanadaCentral, 200 }, @@ -280,9 +287,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 238 }, { LocationNames.FranceSouth, 224 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 250 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 240 }, { LocationNames.IsraelCentral, 164 }, { LocationNames.ItalyNorth, 236 }, @@ -294,6 +299,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 143 }, { LocationNames.MalaysiaSouth, 88 }, { LocationNames.MexicoCentral, 158 }, + { LocationNames.NewZealandNorth, 6 }, { LocationNames.NorthCentralUS, 187 }, { LocationNames.NorthEurope, 258 }, { LocationNames.NorwayEast, 266 }, @@ -305,10 +311,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 170 }, { LocationNames.SoutheastAsia, 88 }, { LocationNames.SouthIndia, 120 }, + { LocationNames.SpainCentral, 238 }, { LocationNames.SwedenCentral, 266 }, { LocationNames.SwedenSouth, 266 }, { LocationNames.SwitzerlandNorth, 236 }, { LocationNames.SwitzerlandWest, 232 }, + { LocationNames.TaiwanNorth, 116 }, + { LocationNames.TaiwanNorthwest, 116 }, { LocationNames.UAECentral, 164 }, { LocationNames.UAENorth, 163 }, { LocationNames.UKSouth, 246 }, @@ -341,6 +350,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 18 }, { LocationNames.AustraliaEast, 14 }, { LocationNames.AustraliaSoutheast, 0 }, + { LocationNames.AustriaEast, 232 }, { LocationNames.BrazilSouth, 320 }, { LocationNames.BrazilSoutheast, 320 }, { LocationNames.CanadaCentral, 210 }, @@ -359,9 +369,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 235 }, { LocationNames.FranceSouth, 222 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 246 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 238 }, { LocationNames.IsraelCentral, 160 }, { LocationNames.ItalyNorth, 232 }, @@ -373,6 +381,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 140 }, { LocationNames.MalaysiaSouth, 85 }, { LocationNames.MexicoCentral, 168 }, + { LocationNames.NewZealandNorth, 18 }, { LocationNames.NorthCentralUS, 198 }, { LocationNames.NorthEurope, 260 }, { LocationNames.NorwayEast, 264 }, @@ -384,10 +393,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 180 }, { LocationNames.SoutheastAsia, 85 }, { LocationNames.SouthIndia, 118 }, + { LocationNames.SpainCentral, 235 }, { LocationNames.SwedenCentral, 264 }, { LocationNames.SwedenSouth, 264 }, { LocationNames.SwitzerlandNorth, 232 }, { LocationNames.SwitzerlandWest, 228 }, + { LocationNames.TaiwanNorth, 118 }, + { LocationNames.TaiwanNorthwest, 118 }, { LocationNames.UAECentral, 160 }, { LocationNames.UAENorth, 160 }, { LocationNames.UKSouth, 242 }, @@ -412,6 +424,88 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUS2EUAP, long.MaxValue }, } }, + { + LocationNames.AustriaEast, + new Dictionary() + { + { LocationNames.AustraliaCentral, 240 }, + { LocationNames.AustraliaCentral2, 240 }, + { LocationNames.AustraliaEast, 236 }, + { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 0 }, + { LocationNames.BrazilSouth, 198 }, + { LocationNames.BrazilSoutheast, 198 }, + { LocationNames.CanadaCentral, 104 }, + { LocationNames.CanadaEast, 114 }, + { LocationNames.CentralIndia, 112 }, + { LocationNames.CentralUS, 112 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 182 }, + { LocationNames.EastUS, 92 }, + { LocationNames.EastUS2, 94 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.FranceCentral, 14 }, + { LocationNames.FranceSouth, 10 }, + { LocationNames.GermanyNorth, 16 }, + { LocationNames.GermanyWestCentral, 6 }, + { LocationNames.IsraelCentral, 106 }, + { LocationNames.ItalyNorth, 100 }, + { LocationNames.JapanEast, 216 }, + { LocationNames.JapanWest, 216 }, + { LocationNames.JioIndiaCentral, 112 }, + { LocationNames.JioIndiaWest, 112 }, + { LocationNames.KoreaCentral, 210 }, + { LocationNames.KoreaSouth, 204 }, + { LocationNames.MalaysiaSouth, 148 }, + { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, + { LocationNames.NorthCentralUS, 110 }, + { LocationNames.NorthEurope, 31 }, + { LocationNames.NorwayEast, 32 }, + { LocationNames.NorwayWest, 26 }, + { LocationNames.PolandCentral, 12 }, + { LocationNames.QatarCentral, 106 }, + { LocationNames.SouthAfricaNorth, 172 }, + { LocationNames.SouthAfricaWest, 162 }, + { LocationNames.SouthCentralUS, 118 }, + { LocationNames.SoutheastAsia, 148 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, + { LocationNames.SwedenCentral, 32 }, + { LocationNames.SwedenSouth, 255 }, + { LocationNames.SwitzerlandNorth, 100 }, + { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, + { LocationNames.UAECentral, 106 }, + { LocationNames.UAENorth, 108 }, + { LocationNames.UKSouth, 20 }, + { LocationNames.UKWest, 22 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 134 }, + { LocationNames.WestEurope, 12 }, + { LocationNames.WestIndia, 116 }, + { LocationNames.WestUS, 150 }, + { LocationNames.WestUS2, 154 }, + { LocationNames.WestUS3, 154 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, { LocationNames.BrazilSouth, new Dictionary() @@ -420,6 +514,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 313 }, { LocationNames.AustraliaEast, 308 }, { LocationNames.AustraliaSoutheast, 320 }, + { LocationNames.AustriaEast, 198 }, { LocationNames.BrazilSouth, 0 }, { LocationNames.BrazilSoutheast, 10 }, { LocationNames.CanadaCentral, 132 }, @@ -438,9 +533,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 186 }, { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 198 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 192 }, { LocationNames.IsraelCentral, 296 }, { LocationNames.ItalyNorth, 198 }, @@ -452,6 +545,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 306 }, { LocationNames.MalaysiaSouth, 328 }, { LocationNames.MexicoCentral, 182 }, + { LocationNames.NewZealandNorth, 314 }, { LocationNames.NorthCentralUS, 138 }, { LocationNames.NorthEurope, 177 }, { LocationNames.NorwayEast, 208 }, @@ -463,10 +557,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 140 }, { LocationNames.SoutheastAsia, 328 }, { LocationNames.SouthIndia, 314 }, + { LocationNames.SpainCentral, 186 }, { LocationNames.SwedenCentral, 208 }, { LocationNames.SwedenSouth, 208 }, { LocationNames.SwitzerlandNorth, 198 }, { LocationNames.SwitzerlandWest, 202 }, + { LocationNames.TaiwanNorth, 320 }, + { LocationNames.TaiwanNorthwest, 320 }, { LocationNames.UAECentral, 296 }, { LocationNames.UAENorth, 298 }, { LocationNames.UKSouth, 181 }, @@ -499,6 +596,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 313 }, { LocationNames.AustraliaEast, 308 }, { LocationNames.AustraliaSoutheast, 320 }, + { LocationNames.AustriaEast, 198 }, { LocationNames.BrazilSouth, 10 }, { LocationNames.BrazilSoutheast, 0 }, { LocationNames.CanadaCentral, 132 }, @@ -517,9 +615,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 186 }, { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 198 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 192 }, { LocationNames.IsraelCentral, 296 }, { LocationNames.ItalyNorth, 198 }, @@ -531,6 +627,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 306 }, { LocationNames.MalaysiaSouth, 328 }, { LocationNames.MexicoCentral, 182 }, + { LocationNames.NewZealandNorth, 314 }, { LocationNames.NorthCentralUS, 138 }, { LocationNames.NorthEurope, 177 }, { LocationNames.NorwayEast, 208 }, @@ -542,10 +639,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 140 }, { LocationNames.SoutheastAsia, 328 }, { LocationNames.SouthIndia, 314 }, + { LocationNames.SpainCentral, 186 }, { LocationNames.SwedenCentral, 208 }, { LocationNames.SwedenSouth, 208 }, { LocationNames.SwitzerlandNorth, 198 }, { LocationNames.SwitzerlandWest, 202 }, + { LocationNames.TaiwanNorth, 320 }, + { LocationNames.TaiwanNorthwest, 320 }, { LocationNames.UAECentral, 296 }, { LocationNames.UAENorth, 298 }, { LocationNames.UKSouth, 181 }, @@ -578,6 +678,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 204 }, { LocationNames.AustraliaEast, 200 }, { LocationNames.AustraliaSoutheast, 210 }, + { LocationNames.AustriaEast, 104 }, { LocationNames.BrazilSouth, 132 }, { LocationNames.BrazilSoutheast, 132 }, { LocationNames.CanadaCentral, 0 }, @@ -596,9 +697,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 92 }, { LocationNames.FranceSouth, 106 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 104 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 98 }, { LocationNames.IsraelCentral, 201 }, { LocationNames.ItalyNorth, 104 }, @@ -610,6 +709,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 182 }, { LocationNames.MalaysiaSouth, 216 }, { LocationNames.MexicoCentral, 57 }, + { LocationNames.NewZealandNorth, 204 }, { LocationNames.NorthCentralUS, 14 }, { LocationNames.NorthEurope, 84 }, { LocationNames.NorwayEast, 114 }, @@ -621,10 +721,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 42 }, { LocationNames.SoutheastAsia, 216 }, { LocationNames.SouthIndia, 220 }, + { LocationNames.SpainCentral, 92 }, { LocationNames.SwedenCentral, 114 }, { LocationNames.SwedenSouth, 114 }, { LocationNames.SwitzerlandNorth, 104 }, { LocationNames.SwitzerlandWest, 108 }, + { LocationNames.TaiwanNorth, 196 }, + { LocationNames.TaiwanNorthwest, 196 }, { LocationNames.UAECentral, 201 }, { LocationNames.UAENorth, 204 }, { LocationNames.UKSouth, 86 }, @@ -657,6 +760,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 214 }, { LocationNames.AustraliaEast, 210 }, { LocationNames.AustraliaSoutheast, 220 }, + { LocationNames.AustriaEast, 114 }, { LocationNames.BrazilSouth, 141 }, { LocationNames.BrazilSoutheast, 141 }, { LocationNames.CanadaCentral, 12 }, @@ -675,9 +779,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 102 }, { LocationNames.FranceSouth, 116 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 114 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 108 }, { LocationNames.IsraelCentral, 210 }, { LocationNames.ItalyNorth, 114 }, @@ -689,6 +791,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 192 }, { LocationNames.MalaysiaSouth, 224 }, { LocationNames.MexicoCentral, 66 }, + { LocationNames.NewZealandNorth, 214 }, { LocationNames.NorthCentralUS, 24 }, { LocationNames.NorthEurope, 93 }, { LocationNames.NorwayEast, 124 }, @@ -700,10 +803,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 52 }, { LocationNames.SoutheastAsia, 224 }, { LocationNames.SouthIndia, 230 }, + { LocationNames.SpainCentral, 102 }, { LocationNames.SwedenCentral, 124 }, { LocationNames.SwedenSouth, 124 }, { LocationNames.SwitzerlandNorth, 114 }, { LocationNames.SwitzerlandWest, 118 }, + { LocationNames.TaiwanNorth, 206 }, + { LocationNames.TaiwanNorthwest, 206 }, { LocationNames.UAECentral, 210 }, { LocationNames.UAENorth, 214 }, { LocationNames.UKSouth, 96 }, @@ -736,6 +842,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 144 }, { LocationNames.AustraliaEast, 140 }, { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, { LocationNames.BrazilSouth, 302 }, { LocationNames.BrazilSoutheast, 302 }, { LocationNames.CanadaCentral, 208 }, @@ -754,9 +861,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 116 }, { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 118 }, { LocationNames.IsraelCentral, 30 }, { LocationNames.ItalyNorth, 112 }, @@ -768,6 +873,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 106 }, { LocationNames.MalaysiaSouth, 52 }, { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, { LocationNames.NorthCentralUS, 216 }, { LocationNames.NorthEurope, 137 }, { LocationNames.NorwayEast, 146 }, @@ -779,10 +885,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 224 }, { LocationNames.SoutheastAsia, 52 }, { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, { LocationNames.SwedenCentral, 146 }, { LocationNames.SwedenSouth, 146 }, { LocationNames.SwitzerlandNorth, 112 }, { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, { LocationNames.UAECentral, 30 }, { LocationNames.UAENorth, 30 }, { LocationNames.UKSouth, 122 }, @@ -815,6 +924,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 184 }, { LocationNames.AustraliaEast, 180 }, { LocationNames.AustraliaSoutheast, 190 }, + { LocationNames.AustriaEast, 112 }, { LocationNames.BrazilSouth, 146 }, { LocationNames.BrazilSoutheast, 146 }, { LocationNames.CanadaCentral, 21 }, @@ -833,9 +943,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 101 }, { LocationNames.FranceSouth, 110 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 118 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 112 }, { LocationNames.IsraelCentral, 216 }, { LocationNames.ItalyNorth, 112 }, @@ -847,6 +955,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 162 }, { LocationNames.MalaysiaSouth, 194 }, { LocationNames.MexicoCentral, 36 }, + { LocationNames.NewZealandNorth, 184 }, { LocationNames.NorthCentralUS, 8 }, { LocationNames.NorthEurope, 92 }, { LocationNames.NorwayEast, 128 }, @@ -858,10 +967,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 22 }, { LocationNames.SoutheastAsia, 194 }, { LocationNames.SouthIndia, 228 }, + { LocationNames.SpainCentral, 101 }, { LocationNames.SwedenCentral, 128 }, { LocationNames.SwedenSouth, 128 }, { LocationNames.SwitzerlandNorth, 112 }, { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 176 }, + { LocationNames.TaiwanNorthwest, 176 }, { LocationNames.UAECentral, 216 }, { LocationNames.UAENorth, 218 }, { LocationNames.UKSouth, 96 }, @@ -894,6 +1006,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -912,9 +1025,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -926,6 +1037,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -937,10 +1049,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -973,6 +1088,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -991,9 +1107,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1005,6 +1119,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1016,10 +1131,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1052,6 +1170,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -1070,9 +1189,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1084,6 +1201,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1095,10 +1213,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1131,6 +1252,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -1149,9 +1271,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1163,6 +1283,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1174,10 +1295,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1210,6 +1334,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -1228,9 +1353,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1242,6 +1365,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1253,10 +1377,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1289,6 +1416,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -1307,9 +1435,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1321,6 +1447,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1332,10 +1459,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1368,6 +1498,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 120 }, { LocationNames.AustraliaEast, 116 }, { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, { LocationNames.BrazilSouth, 320 }, { LocationNames.BrazilSoutheast, 320 }, { LocationNames.CanadaCentral, 196 }, @@ -1386,9 +1517,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 184 }, { LocationNames.FranceSouth, 172 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 196 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 188 }, { LocationNames.IsraelCentral, 110 }, { LocationNames.ItalyNorth, 182 }, @@ -1400,6 +1529,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 60 }, { LocationNames.MalaysiaSouth, 33 }, { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, { LocationNames.NorthCentralUS, 184 }, { LocationNames.NorthEurope, 205 }, { LocationNames.NorwayEast, 214 }, @@ -1411,10 +1541,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 182 }, { LocationNames.SoutheastAsia, 33 }, { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, { LocationNames.SwedenCentral, 214 }, { LocationNames.SwedenSouth, 214 }, { LocationNames.SwitzerlandNorth, 182 }, { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 100 }, + { LocationNames.TaiwanNorthwest, 100 }, { LocationNames.UAECentral, 110 }, { LocationNames.UAENorth, 109 }, { LocationNames.UKSouth, 192 }, @@ -1447,6 +1580,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 205 }, { LocationNames.AustraliaEast, 200 }, { LocationNames.AustraliaSoutheast, 212 }, + { LocationNames.AustriaEast, 92 }, { LocationNames.BrazilSouth, 118 }, { LocationNames.BrazilSoutheast, 118 }, { LocationNames.CanadaCentral, 25 }, @@ -1465,9 +1599,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 80 }, { LocationNames.FranceSouth, 90 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 91 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 86 }, { LocationNames.IsraelCentral, 189 }, { LocationNames.ItalyNorth, 92 }, @@ -1479,6 +1611,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 186 }, { LocationNames.MalaysiaSouth, 218 }, { LocationNames.MexicoCentral, 58 }, + { LocationNames.NewZealandNorth, 205 }, { LocationNames.NorthCentralUS, 19 }, { LocationNames.NorthEurope, 76 }, { LocationNames.NorwayEast, 101 }, @@ -1490,10 +1623,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 32 }, { LocationNames.SoutheastAsia, 218 }, { LocationNames.SouthIndia, 208 }, + { LocationNames.SpainCentral, 80 }, { LocationNames.SwedenCentral, 101 }, { LocationNames.SwedenSouth, 101 }, { LocationNames.SwitzerlandNorth, 92 }, { LocationNames.SwitzerlandWest, 88 }, + { LocationNames.TaiwanNorth, 199 }, + { LocationNames.TaiwanNorthwest, 199 }, { LocationNames.UAECentral, 189 }, { LocationNames.UAENorth, 192 }, { LocationNames.UKSouth, 74 }, @@ -1526,6 +1662,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 200 }, { LocationNames.AustraliaEast, 196 }, { LocationNames.AustraliaSoutheast, 206 }, + { LocationNames.AustriaEast, 94 }, { LocationNames.BrazilSouth, 122 }, { LocationNames.BrazilSoutheast, 122 }, { LocationNames.CanadaCentral, 28 }, @@ -1544,9 +1681,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 80 }, { LocationNames.FranceSouth, 90 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 94 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 90 }, { LocationNames.IsraelCentral, 190 }, { LocationNames.ItalyNorth, 94 }, @@ -1558,6 +1693,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 182 }, { LocationNames.MalaysiaSouth, 226 }, { LocationNames.MexicoCentral, 68 }, + { LocationNames.NewZealandNorth, 200 }, { LocationNames.NorthCentralUS, 22 }, { LocationNames.NorthEurope, 75 }, { LocationNames.NorwayEast, 104 }, @@ -1569,10 +1705,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 26 }, { LocationNames.SoutheastAsia, 226 }, { LocationNames.SouthIndia, 210 }, + { LocationNames.SpainCentral, 80 }, { LocationNames.SwedenCentral, 104 }, { LocationNames.SwedenSouth, 104 }, { LocationNames.SwitzerlandNorth, 94 }, { LocationNames.SwitzerlandWest, 88 }, + { LocationNames.TaiwanNorth, 210 }, + { LocationNames.TaiwanNorthwest, 210 }, { LocationNames.UAECentral, 190 }, { LocationNames.UAENorth, 194 }, { LocationNames.UKSouth, 78 }, @@ -1605,6 +1744,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -1623,9 +1763,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, 0 }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -1637,6 +1775,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -1648,10 +1787,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, 255 }, { LocationNames.SwedenSouth, 255 }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -1684,6 +1826,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 242 }, { LocationNames.AustraliaEast, 238 }, { LocationNames.AustraliaSoutheast, 235 }, + { LocationNames.AustriaEast, 14 }, { LocationNames.BrazilSouth, 186 }, { LocationNames.BrazilSoutheast, 186 }, { LocationNames.CanadaCentral, 92 }, @@ -1702,9 +1845,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 0 }, { LocationNames.FranceSouth, 11 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 10 }, { LocationNames.IsraelCentral, 108 }, { LocationNames.ItalyNorth, 14 }, @@ -1716,6 +1857,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 206 }, { LocationNames.MalaysiaSouth, 150 }, { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 242 }, { LocationNames.NorthCentralUS, 96 }, { LocationNames.NorthEurope, 27 }, { LocationNames.NorwayEast, 30 }, @@ -1727,10 +1869,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 106 }, { LocationNames.SoutheastAsia, 150 }, { LocationNames.SouthIndia, 128 }, + { LocationNames.SpainCentral, 100 }, { LocationNames.SwedenCentral, 30 }, { LocationNames.SwedenSouth, 30 }, { LocationNames.SwitzerlandNorth, 14 }, { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, { LocationNames.UAECentral, 108 }, { LocationNames.UAENorth, 112 }, { LocationNames.UKSouth, 7 }, @@ -1763,6 +1908,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 230 }, { LocationNames.AustraliaEast, 224 }, { LocationNames.AustraliaSoutheast, 222 }, + { LocationNames.AustriaEast, 10 }, { LocationNames.BrazilSouth, 200 }, { LocationNames.BrazilSoutheast, 200 }, { LocationNames.CanadaCentral, 106 }, @@ -1781,9 +1927,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 11 }, { LocationNames.FranceSouth, 0 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 26 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 17 }, { LocationNames.IsraelCentral, 96 }, { LocationNames.ItalyNorth, 10 }, @@ -1795,6 +1939,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 193 }, { LocationNames.MalaysiaSouth, 138 }, { LocationNames.MexicoCentral, 146 }, + { LocationNames.NewZealandNorth, 230 }, { LocationNames.NorthCentralUS, 104 }, { LocationNames.NorthEurope, 31 }, { LocationNames.NorwayEast, 42 }, @@ -1806,10 +1951,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 116 }, { LocationNames.SoutheastAsia, 138 }, { LocationNames.SouthIndia, 114 }, + { LocationNames.SpainCentral, 11 }, { LocationNames.SwedenCentral, 42 }, { LocationNames.SwedenSouth, 42 }, { LocationNames.SwitzerlandNorth, 10 }, { LocationNames.SwitzerlandWest, 8 }, + { LocationNames.TaiwanNorth, 172 }, + { LocationNames.TaiwanNorthwest, 172 }, { LocationNames.UAECentral, 96 }, { LocationNames.UAENorth, 98 }, { LocationNames.UKSouth, 16 }, @@ -1834,85 +1982,6 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUS2EUAP, long.MaxValue }, } }, - { - LocationNames.GermanyCentral, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, 0 }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, 10 }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, { LocationNames.GermanyNorth, new Dictionary() @@ -1921,6 +1990,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 256 }, { LocationNames.AustraliaEast, 250 }, { LocationNames.AustraliaSoutheast, 246 }, + { LocationNames.AustriaEast, 16 }, { LocationNames.BrazilSouth, 198 }, { LocationNames.BrazilSoutheast, 198 }, { LocationNames.CanadaCentral, 104 }, @@ -1939,9 +2009,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 20 }, { LocationNames.FranceSouth, 26 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 0 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 10 }, { LocationNames.IsraelCentral, 120 }, { LocationNames.ItalyNorth, 16 }, @@ -1953,6 +2021,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 218 }, { LocationNames.MalaysiaSouth, 162 }, { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 254 }, { LocationNames.NorthCentralUS, 112 }, { LocationNames.NorthEurope, 31 }, { LocationNames.NorwayEast, 20 }, @@ -1964,10 +2033,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 120 }, { LocationNames.SoutheastAsia, 162 }, { LocationNames.SouthIndia, 140 }, + { LocationNames.SpainCentral, 20 }, { LocationNames.SwedenCentral, 20 }, { LocationNames.SwedenSouth, 20 }, { LocationNames.SwitzerlandNorth, 16 }, { LocationNames.SwitzerlandWest, 20 }, + { LocationNames.TaiwanNorth, 196 }, + { LocationNames.TaiwanNorthwest, 196 }, { LocationNames.UAECentral, 120 }, { LocationNames.UAENorth, 124 }, { LocationNames.UKSouth, 20 }, @@ -1992,85 +2064,6 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUS2EUAP, long.MaxValue }, } }, - { - LocationNames.GermanyNortheast, - new Dictionary() - { - { LocationNames.AustraliaCentral, long.MaxValue }, - { LocationNames.AustraliaCentral2, long.MaxValue }, - { LocationNames.AustraliaEast, long.MaxValue }, - { LocationNames.AustraliaSoutheast, long.MaxValue }, - { LocationNames.BrazilSouth, long.MaxValue }, - { LocationNames.BrazilSoutheast, long.MaxValue }, - { LocationNames.CanadaCentral, long.MaxValue }, - { LocationNames.CanadaEast, long.MaxValue }, - { LocationNames.CentralIndia, long.MaxValue }, - { LocationNames.CentralUS, long.MaxValue }, - { LocationNames.ChinaEast, long.MaxValue }, - { LocationNames.ChinaEast2, long.MaxValue }, - { LocationNames.ChinaEast3, long.MaxValue }, - { LocationNames.ChinaNorth, long.MaxValue }, - { LocationNames.ChinaNorth2, long.MaxValue }, - { LocationNames.ChinaNorth3, long.MaxValue }, - { LocationNames.EastAsia, long.MaxValue }, - { LocationNames.EastUS, long.MaxValue }, - { LocationNames.EastUS2, long.MaxValue }, - { LocationNames.EastUSSLV, long.MaxValue }, - { LocationNames.FranceCentral, long.MaxValue }, - { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, 10 }, - { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, 0 }, - { LocationNames.GermanyWestCentral, long.MaxValue }, - { LocationNames.IsraelCentral, long.MaxValue }, - { LocationNames.ItalyNorth, long.MaxValue }, - { LocationNames.JapanEast, long.MaxValue }, - { LocationNames.JapanWest, long.MaxValue }, - { LocationNames.JioIndiaCentral, long.MaxValue }, - { LocationNames.JioIndiaWest, long.MaxValue }, - { LocationNames.KoreaCentral, long.MaxValue }, - { LocationNames.KoreaSouth, long.MaxValue }, - { LocationNames.MalaysiaSouth, long.MaxValue }, - { LocationNames.MexicoCentral, long.MaxValue }, - { LocationNames.NorthCentralUS, long.MaxValue }, - { LocationNames.NorthEurope, long.MaxValue }, - { LocationNames.NorwayEast, long.MaxValue }, - { LocationNames.NorwayWest, long.MaxValue }, - { LocationNames.PolandCentral, long.MaxValue }, - { LocationNames.QatarCentral, long.MaxValue }, - { LocationNames.SouthAfricaNorth, long.MaxValue }, - { LocationNames.SouthAfricaWest, long.MaxValue }, - { LocationNames.SouthCentralUS, long.MaxValue }, - { LocationNames.SoutheastAsia, long.MaxValue }, - { LocationNames.SouthIndia, long.MaxValue }, - { LocationNames.SwedenCentral, long.MaxValue }, - { LocationNames.SwedenSouth, long.MaxValue }, - { LocationNames.SwitzerlandNorth, long.MaxValue }, - { LocationNames.SwitzerlandWest, long.MaxValue }, - { LocationNames.UAECentral, long.MaxValue }, - { LocationNames.UAENorth, long.MaxValue }, - { LocationNames.UKSouth, long.MaxValue }, - { LocationNames.UKWest, long.MaxValue }, - { LocationNames.USDoDCentral, long.MaxValue }, - { LocationNames.USDoDEast, long.MaxValue }, - { LocationNames.USGovArizona, long.MaxValue }, - { LocationNames.USGovTexas, long.MaxValue }, - { LocationNames.USGovVirginia, long.MaxValue }, - { LocationNames.USNatEast, long.MaxValue }, - { LocationNames.USNatWest, long.MaxValue }, - { LocationNames.USSecEast, long.MaxValue }, - { LocationNames.USSecWest, long.MaxValue }, - { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, long.MaxValue }, - { LocationNames.WestEurope, long.MaxValue }, - { LocationNames.WestIndia, long.MaxValue }, - { LocationNames.WestUS, long.MaxValue }, - { LocationNames.WestUS2, long.MaxValue }, - { LocationNames.WestUS3, long.MaxValue }, - { LocationNames.CentralUSEUAP, long.MaxValue }, - { LocationNames.EastUS2EUAP, long.MaxValue }, - } - }, { LocationNames.GermanyWestCentral, new Dictionary() @@ -2079,6 +2072,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 246 }, { LocationNames.AustraliaEast, 240 }, { LocationNames.AustraliaSoutheast, 238 }, + { LocationNames.AustriaEast, 6 }, { LocationNames.BrazilSouth, 192 }, { LocationNames.BrazilSoutheast, 192 }, { LocationNames.CanadaCentral, 98 }, @@ -2097,9 +2091,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 10 }, { LocationNames.FranceSouth, 17 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 0 }, { LocationNames.IsraelCentral, 112 }, { LocationNames.ItalyNorth, 6 }, @@ -2111,6 +2103,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 209 }, { LocationNames.MalaysiaSouth, 154 }, { LocationNames.MexicoCentral, 148 }, + { LocationNames.NewZealandNorth, 246 }, { LocationNames.NorthCentralUS, 106 }, { LocationNames.NorthEurope, 25 }, { LocationNames.NorwayEast, 26 }, @@ -2122,10 +2115,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 116 }, { LocationNames.SoutheastAsia, 154 }, { LocationNames.SouthIndia, 130 }, + { LocationNames.SpainCentral, 10 }, { LocationNames.SwedenCentral, 26 }, { LocationNames.SwedenSouth, 26 }, { LocationNames.SwitzerlandNorth, 6 }, { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 188 }, + { LocationNames.TaiwanNorthwest, 188 }, { LocationNames.UAECentral, 112 }, { LocationNames.UAENorth, 114 }, { LocationNames.UKSouth, 14 }, @@ -2158,6 +2154,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 168 }, { LocationNames.AustraliaEast, 164 }, { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, { LocationNames.BrazilSouth, 296 }, { LocationNames.BrazilSoutheast, 296 }, { LocationNames.CanadaCentral, 201 }, @@ -2176,9 +2173,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 108 }, { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 112 }, { LocationNames.IsraelCentral, 0 }, { LocationNames.ItalyNorth, 106 }, @@ -2190,6 +2185,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 132 }, { LocationNames.MalaysiaSouth, 76 }, { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, { LocationNames.NorthCentralUS, 209 }, { LocationNames.NorthEurope, 129 }, { LocationNames.NorwayEast, 138 }, @@ -2201,10 +2197,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 218 }, { LocationNames.SoutheastAsia, 76 }, { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, { LocationNames.SwedenCentral, 129 }, { LocationNames.SwedenSouth, 129 }, { LocationNames.SwitzerlandNorth, 106 }, { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, { LocationNames.UAECentral, 100 }, { LocationNames.UAENorth, 4 }, { LocationNames.UKSouth, 116 }, @@ -2237,6 +2236,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 240 }, { LocationNames.AustraliaEast, 236 }, { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 100 }, { LocationNames.BrazilSouth, 198 }, { LocationNames.BrazilSoutheast, 198 }, { LocationNames.CanadaCentral, 104 }, @@ -2255,9 +2255,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 14 }, { LocationNames.FranceSouth, 10 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 16 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 6 }, { LocationNames.IsraelCentral, 106 }, { LocationNames.ItalyNorth, 0 }, @@ -2269,6 +2267,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 204 }, { LocationNames.MalaysiaSouth, 148 }, { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, { LocationNames.NorthCentralUS, 110 }, { LocationNames.NorthEurope, 31 }, { LocationNames.NorwayEast, 32 }, @@ -2280,10 +2279,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 118 }, { LocationNames.SoutheastAsia, 148 }, { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, { LocationNames.SwedenCentral, 32 }, { LocationNames.SwedenSouth, 255 }, { LocationNames.SwitzerlandNorth, 100 }, { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, { LocationNames.UAECentral, 106 }, { LocationNames.UAENorth, 108 }, { LocationNames.UKSouth, 20 }, @@ -2316,6 +2318,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 124 }, { LocationNames.AustraliaEast, 118 }, { LocationNames.AustraliaSoutheast, 130 }, + { LocationNames.AustriaEast, 216 }, { LocationNames.BrazilSouth, 262 }, { LocationNames.BrazilSoutheast, 262 }, { LocationNames.CanadaCentral, 152 }, @@ -2334,9 +2337,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 218 }, { LocationNames.FranceSouth, 204 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 230 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 220 }, { LocationNames.IsraelCentral, 144 }, { LocationNames.ItalyNorth, 216 }, @@ -2348,6 +2349,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 35 }, { LocationNames.MalaysiaSouth, 68 }, { LocationNames.MexicoCentral, 112 }, + { LocationNames.NewZealandNorth, 125 }, { LocationNames.NorthCentralUS, 148 }, { LocationNames.NorthEurope, 223 }, { LocationNames.NorwayEast, 254 }, @@ -2359,10 +2361,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 138 }, { LocationNames.SoutheastAsia, 68 }, { LocationNames.SouthIndia, 100 }, + { LocationNames.SpainCentral, 218 }, { LocationNames.SwedenCentral, 254 }, { LocationNames.SwedenSouth, 254 }, { LocationNames.SwitzerlandNorth, 216 }, { LocationNames.SwitzerlandWest, 212 }, + { LocationNames.TaiwanNorth, 50 }, + { LocationNames.TaiwanNorthwest, 50 }, { LocationNames.UAECentral, 144 }, { LocationNames.UAENorth, 144 }, { LocationNames.UKSouth, 226 }, @@ -2395,6 +2400,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 132 }, { LocationNames.AustraliaEast, 126 }, { LocationNames.AustraliaSoutheast, 138 }, + { LocationNames.AustriaEast, 216 }, { LocationNames.BrazilSouth, 270 }, { LocationNames.BrazilSoutheast, 270 }, { LocationNames.CanadaCentral, 160 }, @@ -2413,9 +2419,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 218 }, { LocationNames.FranceSouth, 206 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 230 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 220 }, { LocationNames.IsraelCentral, 149 }, { LocationNames.ItalyNorth, 216 }, @@ -2427,6 +2431,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 42 }, { LocationNames.MalaysiaSouth, 74 }, { LocationNames.MexicoCentral, 112 }, + { LocationNames.NewZealandNorth, 130 }, { LocationNames.NorthCentralUS, 152 }, { LocationNames.NorthEurope, 236 }, { LocationNames.NorwayEast, 248 }, @@ -2438,10 +2443,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 138 }, { LocationNames.SoutheastAsia, 74 }, { LocationNames.SouthIndia, 104 }, + { LocationNames.SpainCentral, 218 }, { LocationNames.SwedenCentral, 248 }, { LocationNames.SwedenSouth, 248 }, { LocationNames.SwitzerlandNorth, 216 }, { LocationNames.SwitzerlandWest, 210 }, + { LocationNames.TaiwanNorth, 50 }, + { LocationNames.TaiwanNorthwest, 50 }, { LocationNames.UAECentral, 149 }, { LocationNames.UAENorth, 148 }, { LocationNames.UKSouth, 225 }, @@ -2474,6 +2482,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 144 }, { LocationNames.AustraliaEast, 140 }, { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, { LocationNames.BrazilSouth, 302 }, { LocationNames.BrazilSoutheast, 302 }, { LocationNames.CanadaCentral, 208 }, @@ -2492,9 +2501,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 116 }, { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 118 }, { LocationNames.IsraelCentral, 30 }, { LocationNames.ItalyNorth, 112 }, @@ -2506,6 +2513,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 106 }, { LocationNames.MalaysiaSouth, 52 }, { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, { LocationNames.NorthCentralUS, 216 }, { LocationNames.NorthEurope, 137 }, { LocationNames.NorwayEast, 146 }, @@ -2517,10 +2525,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 224 }, { LocationNames.SoutheastAsia, 52 }, { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, { LocationNames.SwedenCentral, 146 }, { LocationNames.SwedenSouth, 146 }, { LocationNames.SwitzerlandNorth, 112 }, { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, { LocationNames.UAECentral, 30 }, { LocationNames.UAENorth, 30 }, { LocationNames.UKSouth, 122 }, @@ -2553,6 +2564,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 144 }, { LocationNames.AustraliaEast, 140 }, { LocationNames.AustraliaSoutheast, 136 }, + { LocationNames.AustriaEast, 112 }, { LocationNames.BrazilSouth, 302 }, { LocationNames.BrazilSoutheast, 302 }, { LocationNames.CanadaCentral, 208 }, @@ -2571,9 +2583,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 116 }, { LocationNames.FranceSouth, 102 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 128 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 118 }, { LocationNames.IsraelCentral, 30 }, { LocationNames.ItalyNorth, 112 }, @@ -2585,6 +2595,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 106 }, { LocationNames.MalaysiaSouth, 52 }, { LocationNames.MexicoCentral, 212 }, + { LocationNames.NewZealandNorth, 144 }, { LocationNames.NorthCentralUS, 216 }, { LocationNames.NorthEurope, 137 }, { LocationNames.NorwayEast, 146 }, @@ -2596,10 +2607,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 224 }, { LocationNames.SoutheastAsia, 52 }, { LocationNames.SouthIndia, 22 }, + { LocationNames.SpainCentral, 116 }, { LocationNames.SwedenCentral, 146 }, { LocationNames.SwedenSouth, 146 }, { LocationNames.SwitzerlandNorth, 112 }, { LocationNames.SwitzerlandWest, 110 }, + { LocationNames.TaiwanNorth, 86 }, + { LocationNames.TaiwanNorthwest, 86 }, { LocationNames.UAECentral, 30 }, { LocationNames.UAENorth, 30 }, { LocationNames.UKSouth, 122 }, @@ -2632,6 +2646,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 154 }, { LocationNames.AustraliaEast, 150 }, { LocationNames.AustraliaSoutheast, 146 }, + { LocationNames.AustriaEast, 210 }, { LocationNames.BrazilSouth, 300 }, { LocationNames.BrazilSoutheast, 300 }, { LocationNames.CanadaCentral, 178 }, @@ -2650,9 +2665,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 212 }, { LocationNames.FranceSouth, 200 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 224 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 216 }, { LocationNames.IsraelCentral, 138 }, { LocationNames.ItalyNorth, 210 }, @@ -2664,6 +2677,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 6 }, { LocationNames.MalaysiaSouth, 62 }, { LocationNames.MexicoCentral, 122 }, + { LocationNames.NewZealandNorth, 154 }, { LocationNames.NorthCentralUS, 165 }, { LocationNames.NorthEurope, 233 }, { LocationNames.NorwayEast, 242 }, @@ -2675,10 +2689,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 152 }, { LocationNames.SoutheastAsia, 62 }, { LocationNames.SouthIndia, 95 }, + { LocationNames.SpainCentral, 212 }, { LocationNames.SwedenCentral, 242 }, { LocationNames.SwedenSouth, 242 }, { LocationNames.SwitzerlandNorth, 210 }, { LocationNames.SwitzerlandWest, 206 }, + { LocationNames.TaiwanNorth, 56 }, + { LocationNames.TaiwanNorthwest, 56 }, { LocationNames.UAECentral, 138 }, { LocationNames.UAENorth, 138 }, { LocationNames.UKSouth, 220 }, @@ -2711,6 +2728,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 148 }, { LocationNames.AustraliaEast, 143 }, { LocationNames.AustraliaSoutheast, 140 }, + { LocationNames.AustriaEast, 204 }, { LocationNames.BrazilSouth, 306 }, { LocationNames.BrazilSoutheast, 306 }, { LocationNames.CanadaCentral, 182 }, @@ -2729,9 +2747,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 206 }, { LocationNames.FranceSouth, 193 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 218 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 209 }, { LocationNames.IsraelCentral, 132 }, { LocationNames.ItalyNorth, 204 }, @@ -2743,6 +2759,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 0 }, { LocationNames.MalaysiaSouth, 56 }, { LocationNames.MexicoCentral, 126 }, + { LocationNames.NewZealandNorth, 148 }, { LocationNames.NorthCentralUS, 170 }, { LocationNames.NorthEurope, 226 }, { LocationNames.NorwayEast, 235 }, @@ -2754,10 +2771,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 156 }, { LocationNames.SoutheastAsia, 56 }, { LocationNames.SouthIndia, 88 }, + { LocationNames.SpainCentral, 206 }, { LocationNames.SwedenCentral, 235 }, { LocationNames.SwedenSouth, 235 }, { LocationNames.SwitzerlandNorth, 204 }, { LocationNames.SwitzerlandWest, 200 }, + { LocationNames.TaiwanNorth, 60 }, + { LocationNames.TaiwanNorthwest, 60 }, { LocationNames.UAECentral, 132 }, { LocationNames.UAENorth, 130 }, { LocationNames.UKSouth, 214 }, @@ -2790,6 +2810,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 92 }, { LocationNames.AustraliaEast, 88 }, { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, { LocationNames.BrazilSouth, 328 }, { LocationNames.BrazilSoutheast, 328 }, { LocationNames.CanadaCentral, 216 }, @@ -2808,9 +2829,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 150 }, { LocationNames.FranceSouth, 138 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 154 }, { LocationNames.IsraelCentral, 76 }, { LocationNames.ItalyNorth, 148 }, @@ -2822,6 +2841,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 56 }, { LocationNames.MalaysiaSouth, 0 }, { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, { LocationNames.NorthCentralUS, 202 }, { LocationNames.NorthEurope, 172 }, { LocationNames.NorwayEast, 180 }, @@ -2833,10 +2853,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 200 }, { LocationNames.SoutheastAsia, 100 }, { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, { LocationNames.SwedenCentral, 180 }, { LocationNames.SwedenSouth, 180 }, { LocationNames.SwitzerlandNorth, 148 }, { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, { LocationNames.UAECentral, 76 }, { LocationNames.UAENorth, 76 }, { LocationNames.UKSouth, 158 }, @@ -2869,6 +2892,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 162 }, { LocationNames.AustraliaEast, 158 }, { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, { LocationNames.BrazilSouth, 182 }, { LocationNames.BrazilSoutheast, 182 }, { LocationNames.CanadaCentral, 57 }, @@ -2887,9 +2911,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 140 }, { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 148 }, { LocationNames.IsraelCentral, 236 }, { LocationNames.ItalyNorth, 154 }, @@ -2901,6 +2923,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 126 }, { LocationNames.MalaysiaSouth, 160 }, { LocationNames.MexicoCentral, 0 }, + { LocationNames.NewZealandNorth, 162 }, { LocationNames.NorthCentralUS, 44 }, { LocationNames.NorthEurope, 136 }, { LocationNames.NorwayEast, 164 }, @@ -2912,10 +2935,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 44 }, { LocationNames.SoutheastAsia, 160 }, { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, { LocationNames.SwedenCentral, 164 }, { LocationNames.SwedenSouth, 164 }, { LocationNames.SwitzerlandNorth, 154 }, { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, { LocationNames.UAECentral, 236 }, { LocationNames.UAENorth, 236 }, { LocationNames.UKSouth, 130 }, @@ -2930,12 +2956,94 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.USSecEast, long.MaxValue }, { LocationNames.USSecWest, long.MaxValue }, { LocationNames.USSecWestCentral, long.MaxValue }, - { LocationNames.WestCentralUS, 22 }, - { LocationNames.WestEurope, 142 }, - { LocationNames.WestIndia, 210 }, - { LocationNames.WestUS, 22 }, - { LocationNames.WestUS2, 100 }, - { LocationNames.WestUS3, 100 }, + { LocationNames.WestCentralUS, 22 }, + { LocationNames.WestEurope, 142 }, + { LocationNames.WestIndia, 210 }, + { LocationNames.WestUS, 22 }, + { LocationNames.WestUS2, 100 }, + { LocationNames.WestUS3, 100 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.NewZealandNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 100 }, + { LocationNames.AustraliaCentral2, 2 }, + { LocationNames.AustraliaEast, 6 }, + { LocationNames.AustraliaSoutheast, 18 }, + { LocationNames.AustriaEast, 240 }, + { LocationNames.BrazilSouth, 314 }, + { LocationNames.BrazilSoutheast, 314 }, + { LocationNames.CanadaCentral, 204 }, + { LocationNames.CanadaEast, 214 }, + { LocationNames.CentralIndia, 144 }, + { LocationNames.CentralUS, 184 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 120 }, + { LocationNames.EastUS, 205 }, + { LocationNames.EastUS2, 200 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.FranceCentral, 242 }, + { LocationNames.FranceSouth, 230 }, + { LocationNames.GermanyNorth, 254 }, + { LocationNames.GermanyWestCentral, 246 }, + { LocationNames.IsraelCentral, 168 }, + { LocationNames.ItalyNorth, 240 }, + { LocationNames.JapanEast, 125 }, + { LocationNames.JapanWest, 130 }, + { LocationNames.JioIndiaCentral, 144 }, + { LocationNames.JioIndiaWest, 144 }, + { LocationNames.KoreaCentral, 154 }, + { LocationNames.KoreaSouth, 148 }, + { LocationNames.MalaysiaSouth, 94 }, + { LocationNames.MexicoCentral, 162 }, + { LocationNames.NewZealandNorth, 0 }, + { LocationNames.NorthCentralUS, 192 }, + { LocationNames.NorthEurope, 262 }, + { LocationNames.NorwayEast, 272 }, + { LocationNames.NorwayWest, 266 }, + { LocationNames.PolandCentral, 252 }, + { LocationNames.QatarCentral, 168 }, + { LocationNames.SouthAfricaNorth, 390 }, + { LocationNames.SouthAfricaWest, 394 }, + { LocationNames.SouthCentralUS, 174 }, + { LocationNames.SoutheastAsia, 94 }, + { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 242 }, + { LocationNames.SwedenCentral, 272 }, + { LocationNames.SwedenSouth, 272 }, + { LocationNames.SwitzerlandNorth, 240 }, + { LocationNames.SwitzerlandWest, 236 }, + { LocationNames.TaiwanNorth, 120 }, + { LocationNames.TaiwanNorthwest, 120 }, + { LocationNames.UAECentral, 168 }, + { LocationNames.UAENorth, 168 }, + { LocationNames.UKSouth, 250 }, + { LocationNames.UKWest, 252 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 170 }, + { LocationNames.WestEurope, 252 }, + { LocationNames.WestIndia, 142 }, + { LocationNames.WestUS, 142 }, + { LocationNames.WestUS2, 162 }, + { LocationNames.WestUS3, 162 }, { LocationNames.CentralUSEUAP, long.MaxValue }, { LocationNames.EastUS2EUAP, long.MaxValue }, } @@ -2948,6 +3056,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 192 }, { LocationNames.AustraliaEast, 187 }, { LocationNames.AustraliaSoutheast, 198 }, + { LocationNames.AustriaEast, 110 }, { LocationNames.BrazilSouth, 138 }, { LocationNames.BrazilSoutheast, 138 }, { LocationNames.CanadaCentral, 14 }, @@ -2966,9 +3075,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 96 }, { LocationNames.FranceSouth, 104 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 112 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 106 }, { LocationNames.IsraelCentral, 209 }, { LocationNames.ItalyNorth, 110 }, @@ -2980,6 +3087,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 170 }, { LocationNames.MalaysiaSouth, 202 }, { LocationNames.MexicoCentral, 44 }, + { LocationNames.NewZealandNorth, 192 }, { LocationNames.NorthCentralUS, 0 }, { LocationNames.NorthEurope, 90 }, { LocationNames.NorwayEast, 122 }, @@ -2991,10 +3099,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 30 }, { LocationNames.SoutheastAsia, 202 }, { LocationNames.SouthIndia, 228 }, + { LocationNames.SpainCentral, 96 }, { LocationNames.SwedenCentral, 122 }, { LocationNames.SwedenSouth, 122 }, { LocationNames.SwitzerlandNorth, 110 }, { LocationNames.SwitzerlandWest, 106 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, { LocationNames.UAECentral, 209 }, { LocationNames.UAENorth, 212 }, { LocationNames.UKSouth, 90 }, @@ -3027,6 +3138,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 262 }, { LocationNames.AustraliaEast, 258 }, { LocationNames.AustraliaSoutheast, 260 }, + { LocationNames.AustriaEast, 31 }, { LocationNames.BrazilSouth, 177 }, { LocationNames.BrazilSoutheast, 177 }, { LocationNames.CanadaCentral, 84 }, @@ -3045,9 +3157,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 27 }, { LocationNames.FranceSouth, 31 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 31 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 25 }, { LocationNames.IsraelCentral, 129 }, { LocationNames.ItalyNorth, 31 }, @@ -3059,6 +3169,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 226 }, { LocationNames.MalaysiaSouth, 172 }, { LocationNames.MexicoCentral, 136 }, + { LocationNames.NewZealandNorth, 262 }, { LocationNames.NorthCentralUS, 90 }, { LocationNames.NorthEurope, 0 }, { LocationNames.NorwayEast, 40 }, @@ -3070,10 +3181,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 106 }, { LocationNames.SoutheastAsia, 172 }, { LocationNames.SouthIndia, 149 }, + { LocationNames.SpainCentral, 27 }, { LocationNames.SwedenCentral, 40 }, { LocationNames.SwedenSouth, 40 }, { LocationNames.SwitzerlandNorth, 31 }, { LocationNames.SwitzerlandWest, 30 }, + { LocationNames.TaiwanNorth, 205 }, + { LocationNames.TaiwanNorthwest, 205 }, { LocationNames.UAECentral, 129 }, { LocationNames.UAENorth, 132 }, { LocationNames.UKSouth, 21 }, @@ -3106,6 +3220,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 272 }, { LocationNames.AustraliaEast, 266 }, { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 32 }, { LocationNames.BrazilSouth, 208 }, { LocationNames.BrazilSoutheast, 208 }, { LocationNames.CanadaCentral, 114 }, @@ -3124,9 +3239,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 30 }, { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 26 }, { LocationNames.IsraelCentral, 138 }, { LocationNames.ItalyNorth, 32 }, @@ -3138,6 +3251,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 235 }, { LocationNames.MalaysiaSouth, 180 }, { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, { LocationNames.NorthCentralUS, 122 }, { LocationNames.NorthEurope, 40 }, { LocationNames.NorwayEast, 0 }, @@ -3149,10 +3263,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 132 }, { LocationNames.SoutheastAsia, 180 }, { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, { LocationNames.SwedenCentral, 20 }, { LocationNames.SwedenSouth, 20 }, { LocationNames.SwitzerlandNorth, 32 }, { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, { LocationNames.UAECentral, 138 }, { LocationNames.UAENorth, 140 }, { LocationNames.UKSouth, 28 }, @@ -3185,6 +3302,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 266 }, { LocationNames.AustraliaEast, 260 }, { LocationNames.AustraliaSoutheast, 258 }, + { LocationNames.AustriaEast, 26 }, { LocationNames.BrazilSouth, 201 }, { LocationNames.BrazilSoutheast, 201 }, { LocationNames.CanadaCentral, 108 }, @@ -3203,9 +3321,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 24 }, { LocationNames.FranceSouth, 36 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 26 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 20 }, { LocationNames.IsraelCentral, 130 }, { LocationNames.ItalyNorth, 26 }, @@ -3217,6 +3333,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 228 }, { LocationNames.MalaysiaSouth, 174 }, { LocationNames.MexicoCentral, 156 }, + { LocationNames.NewZealandNorth, 266 }, { LocationNames.NorthCentralUS, 114 }, { LocationNames.NorthEurope, 33 }, { LocationNames.NorwayEast, 8 }, @@ -3228,10 +3345,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 124 }, { LocationNames.SoutheastAsia, 174 }, { LocationNames.SouthIndia, 150 }, + { LocationNames.SpainCentral, 24 }, { LocationNames.SwedenCentral, 20 }, { LocationNames.SwedenSouth, 20 }, { LocationNames.SwitzerlandNorth, 26 }, { LocationNames.SwitzerlandWest, 30 }, + { LocationNames.TaiwanNorth, 206 }, + { LocationNames.TaiwanNorthwest, 206 }, { LocationNames.UAECentral, 130 }, { LocationNames.UAENorth, 134 }, { LocationNames.UKSouth, 22 }, @@ -3264,6 +3384,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 252 }, { LocationNames.AustraliaEast, 248 }, { LocationNames.AustraliaSoutheast, 244 }, + { LocationNames.AustriaEast, 12 }, { LocationNames.BrazilSouth, 188 }, { LocationNames.BrazilSoutheast, 188 }, { LocationNames.CanadaCentral, 94 }, @@ -3282,9 +3403,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 10 }, { LocationNames.FranceSouth, 20 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 8 }, { LocationNames.IsraelCentral, 118 }, { LocationNames.ItalyNorth, 12 }, @@ -3296,6 +3415,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 216 }, { LocationNames.MalaysiaSouth, 160 }, { LocationNames.MexicoCentral, 142 }, + { LocationNames.NewZealandNorth, 252 }, { LocationNames.NorthCentralUS, 102 }, { LocationNames.NorthEurope, 22 }, { LocationNames.NorwayEast, 22 }, @@ -3307,10 +3427,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 112 }, { LocationNames.SoutheastAsia, 160 }, { LocationNames.SouthIndia, 136 }, + { LocationNames.SpainCentral, 10 }, { LocationNames.SwedenCentral, 22 }, { LocationNames.SwedenSouth, 22 }, { LocationNames.SwitzerlandNorth, 12 }, { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 193 }, + { LocationNames.TaiwanNorthwest, 193 }, { LocationNames.UAECentral, 118 }, { LocationNames.UAENorth, 120 }, { LocationNames.UKSouth, 10 }, @@ -3343,6 +3466,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 168 }, { LocationNames.AustraliaEast, 164 }, { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, { LocationNames.BrazilSouth, 296 }, { LocationNames.BrazilSoutheast, 296 }, { LocationNames.CanadaCentral, 201 }, @@ -3361,9 +3485,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 108 }, { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 112 }, { LocationNames.IsraelCentral, 4 }, { LocationNames.ItalyNorth, 106 }, @@ -3375,6 +3497,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 132 }, { LocationNames.MalaysiaSouth, 76 }, { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, { LocationNames.NorthCentralUS, 209 }, { LocationNames.NorthEurope, 129 }, { LocationNames.NorwayEast, 138 }, @@ -3386,10 +3509,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 218 }, { LocationNames.SoutheastAsia, 76 }, { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, { LocationNames.SwedenCentral, 129 }, { LocationNames.SwedenSouth, 129 }, { LocationNames.SwitzerlandNorth, 106 }, { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, { LocationNames.UAECentral, 4 }, { LocationNames.UAENorth, 4 }, { LocationNames.UKSouth, 116 }, @@ -3422,6 +3548,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 391 }, { LocationNames.AustraliaEast, 386 }, { LocationNames.AustraliaSoutheast, 382 }, + { LocationNames.AustriaEast, 172 }, { LocationNames.BrazilSouth, 342 }, { LocationNames.BrazilSoutheast, 342 }, { LocationNames.CanadaCentral, 246 }, @@ -3440,9 +3567,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 166 }, { LocationNames.FranceSouth, 162 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 178 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 178 }, { LocationNames.IsraelCentral, 256 }, { LocationNames.ItalyNorth, 172 }, @@ -3454,6 +3579,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 354 }, { LocationNames.MalaysiaSouth, 298 }, { LocationNames.MexicoCentral, 296 }, + { LocationNames.NewZealandNorth, 390 }, { LocationNames.NorthCentralUS, 253 }, { LocationNames.NorthEurope, 179 }, { LocationNames.NorwayEast, 186 }, @@ -3465,10 +3591,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 264 }, { LocationNames.SoutheastAsia, 298 }, { LocationNames.SouthIndia, 276 }, + { LocationNames.SpainCentral, 166 }, { LocationNames.SwedenCentral, 186 }, { LocationNames.SwedenSouth, 186 }, { LocationNames.SwitzerlandNorth, 172 }, { LocationNames.SwitzerlandWest, 168 }, + { LocationNames.TaiwanNorth, 332 }, + { LocationNames.TaiwanNorthwest, 332 }, { LocationNames.UAECentral, 256 }, { LocationNames.UAENorth, 260 }, { LocationNames.UKSouth, 160 }, @@ -3501,6 +3630,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 392 }, { LocationNames.AustraliaEast, 390 }, { LocationNames.AustraliaSoutheast, 386 }, + { LocationNames.AustriaEast, 162 }, { LocationNames.BrazilSouth, 326 }, { LocationNames.BrazilSoutheast, 326 }, { LocationNames.CanadaCentral, 230 }, @@ -3519,9 +3649,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 150 }, { LocationNames.FranceSouth, 166 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 156 }, { LocationNames.IsraelCentral, 260 }, { LocationNames.ItalyNorth, 162 }, @@ -3533,6 +3661,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 358 }, { LocationNames.MalaysiaSouth, 302 }, { LocationNames.MexicoCentral, 280 }, + { LocationNames.NewZealandNorth, 394 }, { LocationNames.NorthCentralUS, 236 }, { LocationNames.NorthEurope, 157 }, { LocationNames.NorwayEast, 170 }, @@ -3544,10 +3673,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 248 }, { LocationNames.SoutheastAsia, 302 }, { LocationNames.SouthIndia, 280 }, + { LocationNames.SpainCentral, 150 }, { LocationNames.SwedenCentral, 170 }, { LocationNames.SwedenSouth, 170 }, { LocationNames.SwitzerlandNorth, 162 }, { LocationNames.SwitzerlandWest, 158 }, + { LocationNames.TaiwanNorth, 336 }, + { LocationNames.TaiwanNorthwest, 336 }, { LocationNames.UAECentral, 260 }, { LocationNames.UAENorth, 264 }, { LocationNames.UKSouth, 144 }, @@ -3580,6 +3712,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 174 }, { LocationNames.AustraliaEast, 170 }, { LocationNames.AustraliaSoutheast, 180 }, + { LocationNames.AustriaEast, 118 }, { LocationNames.BrazilSouth, 140 }, { LocationNames.BrazilSoutheast, 140 }, { LocationNames.CanadaCentral, 42 }, @@ -3598,9 +3731,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 106 }, { LocationNames.FranceSouth, 116 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 116 }, { LocationNames.IsraelCentral, 218 }, { LocationNames.ItalyNorth, 118 }, @@ -3612,6 +3743,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 156 }, { LocationNames.MalaysiaSouth, 200 }, { LocationNames.MexicoCentral, 44 }, + { LocationNames.NewZealandNorth, 174 }, { LocationNames.NorthCentralUS, 30 }, { LocationNames.NorthEurope, 106 }, { LocationNames.NorwayEast, 132 }, @@ -3623,10 +3755,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 0 }, { LocationNames.SoutheastAsia, 200 }, { LocationNames.SouthIndia, 222 }, + { LocationNames.SpainCentral, 106 }, { LocationNames.SwedenCentral, 132 }, { LocationNames.SwedenSouth, 132 }, { LocationNames.SwitzerlandNorth, 118 }, { LocationNames.SwitzerlandWest, 116 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, { LocationNames.UAECentral, 218 }, { LocationNames.UAENorth, 220 }, { LocationNames.UKSouth, 104 }, @@ -3659,6 +3794,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 92 }, { LocationNames.AustraliaEast, 88 }, { LocationNames.AustraliaSoutheast, 85 }, + { LocationNames.AustriaEast, 148 }, { LocationNames.BrazilSouth, 328 }, { LocationNames.BrazilSoutheast, 328 }, { LocationNames.CanadaCentral, 216 }, @@ -3677,9 +3813,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 150 }, { LocationNames.FranceSouth, 138 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 162 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 154 }, { LocationNames.IsraelCentral, 76 }, { LocationNames.ItalyNorth, 148 }, @@ -3691,6 +3825,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 56 }, { LocationNames.MalaysiaSouth, 100 }, { LocationNames.MexicoCentral, 160 }, + { LocationNames.NewZealandNorth, 94 }, { LocationNames.NorthCentralUS, 202 }, { LocationNames.NorthEurope, 172 }, { LocationNames.NorwayEast, 180 }, @@ -3702,10 +3837,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 200 }, { LocationNames.SoutheastAsia, 0 }, { LocationNames.SouthIndia, 34 }, + { LocationNames.SpainCentral, 150 }, { LocationNames.SwedenCentral, 180 }, { LocationNames.SwedenSouth, 180 }, { LocationNames.SwitzerlandNorth, 148 }, { LocationNames.SwitzerlandWest, 144 }, + { LocationNames.TaiwanNorth, 33 }, + { LocationNames.TaiwanNorthwest, 33 }, { LocationNames.UAECentral, 76 }, { LocationNames.UAENorth, 76 }, { LocationNames.UKSouth, 158 }, @@ -3738,6 +3876,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 124 }, { LocationNames.AustraliaEast, 120 }, { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 126 }, { LocationNames.BrazilSouth, 314 }, { LocationNames.BrazilSoutheast, 314 }, { LocationNames.CanadaCentral, 220 }, @@ -3756,9 +3895,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 128 }, { LocationNames.FranceSouth, 114 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 140 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 130 }, { LocationNames.IsraelCentral, 46 }, { LocationNames.ItalyNorth, 126 }, @@ -3770,6 +3907,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 88 }, { LocationNames.MalaysiaSouth, 34 }, { LocationNames.MexicoCentral, 192 }, + { LocationNames.NewZealandNorth, 126 }, { LocationNames.NorthCentralUS, 228 }, { LocationNames.NorthEurope, 149 }, { LocationNames.NorwayEast, 157 }, @@ -3781,10 +3919,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 222 }, { LocationNames.SoutheastAsia, 34 }, { LocationNames.SouthIndia, 0 }, + { LocationNames.SpainCentral, 128 }, { LocationNames.SwedenCentral, 157 }, { LocationNames.SwedenSouth, 157 }, { LocationNames.SwitzerlandNorth, 126 }, { LocationNames.SwitzerlandWest, 122 }, + { LocationNames.TaiwanNorth, 66 }, + { LocationNames.TaiwanNorthwest, 66 }, { LocationNames.UAECentral, 46 }, { LocationNames.UAENorth, 46 }, { LocationNames.UKSouth, 134 }, @@ -3809,6 +3950,88 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUS2EUAP, long.MaxValue }, } }, + { + LocationNames.SpainCentral, + new Dictionary() + { + { LocationNames.AustraliaCentral, 242 }, + { LocationNames.AustraliaCentral2, 242 }, + { LocationNames.AustraliaEast, 238 }, + { LocationNames.AustraliaSoutheast, 235 }, + { LocationNames.AustriaEast, 14 }, + { LocationNames.BrazilSouth, 186 }, + { LocationNames.BrazilSoutheast, 186 }, + { LocationNames.CanadaCentral, 92 }, + { LocationNames.CanadaEast, 102 }, + { LocationNames.CentralIndia, 116 }, + { LocationNames.CentralUS, 101 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 184 }, + { LocationNames.EastUS, 80 }, + { LocationNames.EastUS2, 80 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.FranceCentral, 100 }, + { LocationNames.FranceSouth, 11 }, + { LocationNames.GermanyNorth, 20 }, + { LocationNames.GermanyWestCentral, 10 }, + { LocationNames.IsraelCentral, 108 }, + { LocationNames.ItalyNorth, 14 }, + { LocationNames.JapanEast, 218 }, + { LocationNames.JapanWest, 218 }, + { LocationNames.JioIndiaCentral, 116 }, + { LocationNames.JioIndiaWest, 116 }, + { LocationNames.KoreaCentral, 212 }, + { LocationNames.KoreaSouth, 206 }, + { LocationNames.MalaysiaSouth, 150 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 242 }, + { LocationNames.NorthCentralUS, 96 }, + { LocationNames.NorthEurope, 27 }, + { LocationNames.NorwayEast, 30 }, + { LocationNames.NorwayWest, 24 }, + { LocationNames.PolandCentral, 10 }, + { LocationNames.QatarCentral, 108 }, + { LocationNames.SouthAfricaNorth, 166 }, + { LocationNames.SouthAfricaWest, 150 }, + { LocationNames.SouthCentralUS, 106 }, + { LocationNames.SoutheastAsia, 150 }, + { LocationNames.SouthIndia, 128 }, + { LocationNames.SpainCentral, 0 }, + { LocationNames.SwedenCentral, 30 }, + { LocationNames.SwedenSouth, 30 }, + { LocationNames.SwitzerlandNorth, 14 }, + { LocationNames.SwitzerlandWest, 10 }, + { LocationNames.TaiwanNorth, 184 }, + { LocationNames.TaiwanNorthwest, 184 }, + { LocationNames.UAECentral, 108 }, + { LocationNames.UAENorth, 112 }, + { LocationNames.UKSouth, 7 }, + { LocationNames.UKWest, 8 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 119 }, + { LocationNames.WestEurope, 10 }, + { LocationNames.WestIndia, 118 }, + { LocationNames.WestUS, 138 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, { LocationNames.SwedenCentral, new Dictionary() @@ -3817,6 +4040,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 272 }, { LocationNames.AustraliaEast, 266 }, { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 32 }, { LocationNames.BrazilSouth, 208 }, { LocationNames.BrazilSoutheast, 208 }, { LocationNames.CanadaCentral, 114 }, @@ -3835,9 +4059,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, 255 }, { LocationNames.FranceCentral, 30 }, { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 26 }, { LocationNames.IsraelCentral, 129 }, { LocationNames.ItalyNorth, 32 }, @@ -3849,6 +4071,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 235 }, { LocationNames.MalaysiaSouth, 180 }, { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, { LocationNames.NorthCentralUS, 122 }, { LocationNames.NorthEurope, 40 }, { LocationNames.NorwayEast, 10 }, @@ -3860,10 +4083,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 132 }, { LocationNames.SoutheastAsia, 180 }, { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, { LocationNames.SwedenCentral, 0 }, { LocationNames.SwedenSouth, 10 }, { LocationNames.SwitzerlandNorth, 32 }, { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, { LocationNames.UAECentral, 138 }, { LocationNames.UAENorth, 140 }, { LocationNames.UKSouth, 28 }, @@ -3896,6 +4122,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 272 }, { LocationNames.AustraliaEast, 266 }, { LocationNames.AustraliaSoutheast, 264 }, + { LocationNames.AustriaEast, 255 }, { LocationNames.BrazilSouth, 208 }, { LocationNames.BrazilSoutheast, 208 }, { LocationNames.CanadaCentral, 114 }, @@ -3914,9 +4141,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, 255 }, { LocationNames.FranceCentral, 30 }, { LocationNames.FranceSouth, 42 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 26 }, { LocationNames.IsraelCentral, 129 }, { LocationNames.ItalyNorth, 255 }, @@ -3928,6 +4153,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 235 }, { LocationNames.MalaysiaSouth, 180 }, { LocationNames.MexicoCentral, 164 }, + { LocationNames.NewZealandNorth, 272 }, { LocationNames.NorthCentralUS, 122 }, { LocationNames.NorthEurope, 40 }, { LocationNames.NorwayEast, 10 }, @@ -3939,10 +4165,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 132 }, { LocationNames.SoutheastAsia, 180 }, { LocationNames.SouthIndia, 157 }, + { LocationNames.SpainCentral, 30 }, { LocationNames.SwedenCentral, 5 }, { LocationNames.SwedenSouth, 0 }, { LocationNames.SwitzerlandNorth, 32 }, { LocationNames.SwitzerlandWest, 36 }, + { LocationNames.TaiwanNorth, 214 }, + { LocationNames.TaiwanNorthwest, 214 }, { LocationNames.UAECentral, 138 }, { LocationNames.UAENorth, 140 }, { LocationNames.UKSouth, 28 }, @@ -3975,6 +4204,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 240 }, { LocationNames.AustraliaEast, 236 }, { LocationNames.AustraliaSoutheast, 232 }, + { LocationNames.AustriaEast, 100 }, { LocationNames.BrazilSouth, 198 }, { LocationNames.BrazilSoutheast, 198 }, { LocationNames.CanadaCentral, 104 }, @@ -3993,9 +4223,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 14 }, { LocationNames.FranceSouth, 10 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 16 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 6 }, { LocationNames.IsraelCentral, 106 }, { LocationNames.ItalyNorth, 100 }, @@ -4007,6 +4235,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 204 }, { LocationNames.MalaysiaSouth, 148 }, { LocationNames.MexicoCentral, 154 }, + { LocationNames.NewZealandNorth, 240 }, { LocationNames.NorthCentralUS, 110 }, { LocationNames.NorthEurope, 31 }, { LocationNames.NorwayEast, 32 }, @@ -4018,10 +4247,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 118 }, { LocationNames.SoutheastAsia, 148 }, { LocationNames.SouthIndia, 126 }, + { LocationNames.SpainCentral, 14 }, { LocationNames.SwedenCentral, 32 }, { LocationNames.SwedenSouth, 255 }, { LocationNames.SwitzerlandNorth, 0 }, { LocationNames.SwitzerlandWest, 4 }, + { LocationNames.TaiwanNorth, 182 }, + { LocationNames.TaiwanNorthwest, 182 }, { LocationNames.UAECentral, 106 }, { LocationNames.UAENorth, 108 }, { LocationNames.UKSouth, 20 }, @@ -4054,6 +4286,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 236 }, { LocationNames.AustraliaEast, 232 }, { LocationNames.AustraliaSoutheast, 228 }, + { LocationNames.AustriaEast, 4 }, { LocationNames.BrazilSouth, 202 }, { LocationNames.BrazilSoutheast, 202 }, { LocationNames.CanadaCentral, 108 }, @@ -4072,9 +4305,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 10 }, { LocationNames.FranceSouth, 8 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 10 }, { LocationNames.IsraelCentral, 102 }, { LocationNames.ItalyNorth, 4 }, @@ -4086,6 +4317,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 200 }, { LocationNames.MalaysiaSouth, 144 }, { LocationNames.MexicoCentral, 146 }, + { LocationNames.NewZealandNorth, 236 }, { LocationNames.NorthCentralUS, 106 }, { LocationNames.NorthEurope, 30 }, { LocationNames.NorwayEast, 36 }, @@ -4097,10 +4329,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 116 }, { LocationNames.SoutheastAsia, 144 }, { LocationNames.SouthIndia, 122 }, + { LocationNames.SpainCentral, 10 }, { LocationNames.SwedenCentral, 36 }, { LocationNames.SwedenSouth, 36 }, { LocationNames.SwitzerlandNorth, 4 }, { LocationNames.SwitzerlandWest, 0 }, + { LocationNames.TaiwanNorth, 178 }, + { LocationNames.TaiwanNorthwest, 178 }, { LocationNames.UAECentral, 102 }, { LocationNames.UAENorth, 106 }, { LocationNames.UKSouth, 16 }, @@ -4125,6 +4360,170 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUS2EUAP, long.MaxValue }, } }, + { + LocationNames.TaiwanNorth, + new Dictionary() + { + { LocationNames.AustraliaCentral, 120 }, + { LocationNames.AustraliaCentral2, 120 }, + { LocationNames.AustraliaEast, 116 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 196 }, + { LocationNames.CanadaEast, 206 }, + { LocationNames.CentralIndia, 86 }, + { LocationNames.CentralUS, 176 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 100 }, + { LocationNames.EastUS, 199 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.FranceCentral, 184 }, + { LocationNames.FranceSouth, 172 }, + { LocationNames.GermanyNorth, 196 }, + { LocationNames.GermanyWestCentral, 188 }, + { LocationNames.IsraelCentral, 110 }, + { LocationNames.ItalyNorth, 182 }, + { LocationNames.JapanEast, 50 }, + { LocationNames.JapanWest, 50 }, + { LocationNames.JioIndiaCentral, 86 }, + { LocationNames.JioIndiaWest, 86 }, + { LocationNames.KoreaCentral, 56 }, + { LocationNames.KoreaSouth, 60 }, + { LocationNames.MalaysiaSouth, 33 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, + { LocationNames.NorthCentralUS, 184 }, + { LocationNames.NorthEurope, 205 }, + { LocationNames.NorwayEast, 214 }, + { LocationNames.NorwayWest, 206 }, + { LocationNames.PolandCentral, 193 }, + { LocationNames.QatarCentral, 110 }, + { LocationNames.SouthAfricaNorth, 332 }, + { LocationNames.SouthAfricaWest, 336 }, + { LocationNames.SouthCentralUS, 182 }, + { LocationNames.SoutheastAsia, 33 }, + { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, + { LocationNames.SwedenCentral, 214 }, + { LocationNames.SwedenSouth, 214 }, + { LocationNames.SwitzerlandNorth, 182 }, + { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 0 }, + { LocationNames.TaiwanNorthwest, 100 }, + { LocationNames.UAECentral, 110 }, + { LocationNames.UAENorth, 109 }, + { LocationNames.UKSouth, 192 }, + { LocationNames.UKWest, 194 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 162 }, + { LocationNames.WestEurope, 193 }, + { LocationNames.WestIndia, 84 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, + { + LocationNames.TaiwanNorthwest, + new Dictionary() + { + { LocationNames.AustraliaCentral, 120 }, + { LocationNames.AustraliaCentral2, 120 }, + { LocationNames.AustraliaEast, 116 }, + { LocationNames.AustraliaSoutheast, 118 }, + { LocationNames.AustriaEast, 182 }, + { LocationNames.BrazilSouth, 320 }, + { LocationNames.BrazilSoutheast, 320 }, + { LocationNames.CanadaCentral, 196 }, + { LocationNames.CanadaEast, 206 }, + { LocationNames.CentralIndia, 86 }, + { LocationNames.CentralUS, 176 }, + { LocationNames.ChinaEast, long.MaxValue }, + { LocationNames.ChinaEast2, long.MaxValue }, + { LocationNames.ChinaEast3, long.MaxValue }, + { LocationNames.ChinaNorth, long.MaxValue }, + { LocationNames.ChinaNorth2, long.MaxValue }, + { LocationNames.ChinaNorth3, long.MaxValue }, + { LocationNames.EastAsia, 100 }, + { LocationNames.EastUS, 199 }, + { LocationNames.EastUS2, 210 }, + { LocationNames.EastUSSLV, long.MaxValue }, + { LocationNames.FranceCentral, 184 }, + { LocationNames.FranceSouth, 172 }, + { LocationNames.GermanyNorth, 196 }, + { LocationNames.GermanyWestCentral, 188 }, + { LocationNames.IsraelCentral, 110 }, + { LocationNames.ItalyNorth, 182 }, + { LocationNames.JapanEast, 50 }, + { LocationNames.JapanWest, 50 }, + { LocationNames.JioIndiaCentral, 86 }, + { LocationNames.JioIndiaWest, 86 }, + { LocationNames.KoreaCentral, 56 }, + { LocationNames.KoreaSouth, 60 }, + { LocationNames.MalaysiaSouth, 33 }, + { LocationNames.MexicoCentral, 140 }, + { LocationNames.NewZealandNorth, 120 }, + { LocationNames.NorthCentralUS, 184 }, + { LocationNames.NorthEurope, 205 }, + { LocationNames.NorwayEast, 214 }, + { LocationNames.NorwayWest, 206 }, + { LocationNames.PolandCentral, 193 }, + { LocationNames.QatarCentral, 110 }, + { LocationNames.SouthAfricaNorth, 332 }, + { LocationNames.SouthAfricaWest, 336 }, + { LocationNames.SouthCentralUS, 182 }, + { LocationNames.SoutheastAsia, 33 }, + { LocationNames.SouthIndia, 66 }, + { LocationNames.SpainCentral, 184 }, + { LocationNames.SwedenCentral, 214 }, + { LocationNames.SwedenSouth, 214 }, + { LocationNames.SwitzerlandNorth, 182 }, + { LocationNames.SwitzerlandWest, 178 }, + { LocationNames.TaiwanNorth, 100 }, + { LocationNames.TaiwanNorthwest, 0 }, + { LocationNames.UAECentral, 110 }, + { LocationNames.UAENorth, 109 }, + { LocationNames.UKSouth, 192 }, + { LocationNames.UKWest, 194 }, + { LocationNames.USDoDCentral, long.MaxValue }, + { LocationNames.USDoDEast, long.MaxValue }, + { LocationNames.USGovArizona, long.MaxValue }, + { LocationNames.USGovTexas, long.MaxValue }, + { LocationNames.USGovVirginia, long.MaxValue }, + { LocationNames.USNatEast, long.MaxValue }, + { LocationNames.USNatWest, long.MaxValue }, + { LocationNames.USSecEast, long.MaxValue }, + { LocationNames.USSecWest, long.MaxValue }, + { LocationNames.USSecWestCentral, long.MaxValue }, + { LocationNames.WestCentralUS, 162 }, + { LocationNames.WestEurope, 193 }, + { LocationNames.WestIndia, 84 }, + { LocationNames.WestUS, 148 }, + { LocationNames.WestUS2, 140 }, + { LocationNames.WestUS3, 140 }, + { LocationNames.CentralUSEUAP, long.MaxValue }, + { LocationNames.EastUS2EUAP, long.MaxValue }, + } + }, { LocationNames.UAECentral, new Dictionary() @@ -4133,6 +4532,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 168 }, { LocationNames.AustraliaEast, 164 }, { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 106 }, { LocationNames.BrazilSouth, 296 }, { LocationNames.BrazilSoutheast, 296 }, { LocationNames.CanadaCentral, 201 }, @@ -4151,9 +4551,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 108 }, { LocationNames.FranceSouth, 96 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 120 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 112 }, { LocationNames.IsraelCentral, 100 }, { LocationNames.ItalyNorth, 106 }, @@ -4165,6 +4563,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 132 }, { LocationNames.MalaysiaSouth, 76 }, { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, { LocationNames.NorthCentralUS, 209 }, { LocationNames.NorthEurope, 129 }, { LocationNames.NorwayEast, 138 }, @@ -4176,10 +4575,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 218 }, { LocationNames.SoutheastAsia, 76 }, { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 108 }, { LocationNames.SwedenCentral, 129 }, { LocationNames.SwedenSouth, 129 }, { LocationNames.SwitzerlandNorth, 106 }, { LocationNames.SwitzerlandWest, 102 }, + { LocationNames.TaiwanNorth, 110 }, + { LocationNames.TaiwanNorthwest, 110 }, { LocationNames.UAECentral, 0 }, { LocationNames.UAENorth, 4 }, { LocationNames.UKSouth, 116 }, @@ -4212,6 +4614,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 168 }, { LocationNames.AustraliaEast, 163 }, { LocationNames.AustraliaSoutheast, 160 }, + { LocationNames.AustriaEast, 108 }, { LocationNames.BrazilSouth, 298 }, { LocationNames.BrazilSoutheast, 298 }, { LocationNames.CanadaCentral, 204 }, @@ -4230,9 +4633,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 112 }, { LocationNames.FranceSouth, 98 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 124 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 114 }, { LocationNames.IsraelCentral, 4 }, { LocationNames.ItalyNorth, 108 }, @@ -4244,6 +4645,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 130 }, { LocationNames.MalaysiaSouth, 76 }, { LocationNames.MexicoCentral, 236 }, + { LocationNames.NewZealandNorth, 168 }, { LocationNames.NorthCentralUS, 212 }, { LocationNames.NorthEurope, 132 }, { LocationNames.NorwayEast, 140 }, @@ -4255,10 +4657,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 220 }, { LocationNames.SoutheastAsia, 76 }, { LocationNames.SouthIndia, 46 }, + { LocationNames.SpainCentral, 112 }, { LocationNames.SwedenCentral, 140 }, { LocationNames.SwedenSouth, 140 }, { LocationNames.SwitzerlandNorth, 108 }, { LocationNames.SwitzerlandWest, 106 }, + { LocationNames.TaiwanNorth, 109 }, + { LocationNames.TaiwanNorthwest, 109 }, { LocationNames.UAECentral, 4 }, { LocationNames.UAENorth, 0 }, { LocationNames.UKSouth, 120 }, @@ -4291,6 +4696,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 248 }, { LocationNames.AustraliaEast, 246 }, { LocationNames.AustraliaSoutheast, 242 }, + { LocationNames.AustriaEast, 20 }, { LocationNames.BrazilSouth, 181 }, { LocationNames.BrazilSoutheast, 181 }, { LocationNames.CanadaCentral, 86 }, @@ -4309,9 +4715,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 7 }, { LocationNames.FranceSouth, 16 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 20 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 14 }, { LocationNames.IsraelCentral, 116 }, { LocationNames.ItalyNorth, 20 }, @@ -4323,6 +4727,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 214 }, { LocationNames.MalaysiaSouth, 158 }, { LocationNames.MexicoCentral, 130 }, + { LocationNames.NewZealandNorth, 250 }, { LocationNames.NorthCentralUS, 90 }, { LocationNames.NorthEurope, 21 }, { LocationNames.NorwayEast, 28 }, @@ -4334,10 +4739,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 104 }, { LocationNames.SoutheastAsia, 158 }, { LocationNames.SouthIndia, 134 }, + { LocationNames.SpainCentral, 7 }, { LocationNames.SwedenCentral, 21 }, { LocationNames.SwedenSouth, 21 }, { LocationNames.SwitzerlandNorth, 20 }, { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 192 }, + { LocationNames.TaiwanNorthwest, 192 }, { LocationNames.UAECentral, 116 }, { LocationNames.UAENorth, 120 }, { LocationNames.UKSouth, 0 }, @@ -4370,6 +4778,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 252 }, { LocationNames.AustraliaEast, 248 }, { LocationNames.AustraliaSoutheast, 245 }, + { LocationNames.AustriaEast, 22 }, { LocationNames.BrazilSouth, 184 }, { LocationNames.BrazilSoutheast, 184 }, { LocationNames.CanadaCentral, 90 }, @@ -4388,9 +4797,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 8 }, { LocationNames.FranceSouth, 18 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 22 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 18 }, { LocationNames.IsraelCentral, 118 }, { LocationNames.ItalyNorth, 22 }, @@ -4402,6 +4809,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 216 }, { LocationNames.MalaysiaSouth, 161 }, { LocationNames.MexicoCentral, 132 }, + { LocationNames.NewZealandNorth, 252 }, { LocationNames.NorthCentralUS, 92 }, { LocationNames.NorthEurope, 17 }, { LocationNames.NorwayEast, 30 }, @@ -4413,10 +4821,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 106 }, { LocationNames.SoutheastAsia, 161 }, { LocationNames.SouthIndia, 138 }, + { LocationNames.SpainCentral, 8 }, { LocationNames.SwedenCentral, 30 }, { LocationNames.SwedenSouth, 30 }, { LocationNames.SwitzerlandNorth, 22 }, { LocationNames.SwitzerlandWest, 18 }, + { LocationNames.TaiwanNorth, 194 }, + { LocationNames.TaiwanNorthwest, 194 }, { LocationNames.UAECentral, 118 }, { LocationNames.UAENorth, 122 }, { LocationNames.UKSouth, 4 }, @@ -4449,6 +4860,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4467,9 +4879,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4481,6 +4891,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4492,10 +4903,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4528,6 +4942,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4546,9 +4961,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4560,6 +4973,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4571,10 +4985,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4607,6 +5024,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4625,9 +5043,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4639,6 +5055,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4650,10 +5067,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4686,6 +5106,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4704,9 +5125,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4718,6 +5137,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4729,10 +5149,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4765,6 +5188,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4783,9 +5207,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4797,6 +5219,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4808,10 +5231,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4844,6 +5270,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4862,9 +5289,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4876,6 +5301,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4887,10 +5313,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -4923,6 +5352,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -4941,9 +5371,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -4955,6 +5383,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -4966,10 +5395,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -5002,6 +5434,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -5020,9 +5453,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -5034,6 +5465,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -5045,10 +5477,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -5081,6 +5516,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -5099,9 +5535,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -5113,6 +5547,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -5124,10 +5559,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -5160,6 +5598,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -5178,9 +5617,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -5192,6 +5629,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -5203,10 +5641,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -5239,6 +5680,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 170 }, { LocationNames.AustraliaEast, 166 }, { LocationNames.AustraliaSoutheast, 176 }, + { LocationNames.AustriaEast, 134 }, { LocationNames.BrazilSouth, 160 }, { LocationNames.BrazilSoutheast, 160 }, { LocationNames.CanadaCentral, 36 }, @@ -5257,9 +5699,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 119 }, { LocationNames.FranceSouth, 126 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 132 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 126 }, { LocationNames.IsraelCentral, 230 }, { LocationNames.ItalyNorth, 134 }, @@ -5271,6 +5711,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 148 }, { LocationNames.MalaysiaSouth, 180 }, { LocationNames.MexicoCentral, 22 }, + { LocationNames.NewZealandNorth, 170 }, { LocationNames.NorthCentralUS, 22 }, { LocationNames.NorthEurope, 110 }, { LocationNames.NorwayEast, 142 }, @@ -5282,10 +5723,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 22 }, { LocationNames.SoutheastAsia, 180 }, { LocationNames.SouthIndia, 212 }, + { LocationNames.SpainCentral, 119 }, { LocationNames.SwedenCentral, 142 }, { LocationNames.SwedenSouth, 142 }, { LocationNames.SwitzerlandNorth, 134 }, { LocationNames.SwitzerlandWest, 126 }, + { LocationNames.TaiwanNorth, 162 }, + { LocationNames.TaiwanNorthwest, 162 }, { LocationNames.UAECentral, 230 }, { LocationNames.UAENorth, 234 }, { LocationNames.UKSouth, 110 }, @@ -5318,6 +5762,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 252 }, { LocationNames.AustraliaEast, 248 }, { LocationNames.AustraliaSoutheast, 244 }, + { LocationNames.AustriaEast, 12 }, { LocationNames.BrazilSouth, 188 }, { LocationNames.BrazilSoutheast, 188 }, { LocationNames.CanadaCentral, 94 }, @@ -5336,9 +5781,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 10 }, { LocationNames.FranceSouth, 20 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 10 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 8 }, { LocationNames.IsraelCentral, 118 }, { LocationNames.ItalyNorth, 12 }, @@ -5350,6 +5793,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 216 }, { LocationNames.MalaysiaSouth, 160 }, { LocationNames.MexicoCentral, 142 }, + { LocationNames.NewZealandNorth, 252 }, { LocationNames.NorthCentralUS, 102 }, { LocationNames.NorthEurope, 22 }, { LocationNames.NorwayEast, 22 }, @@ -5361,10 +5805,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 112 }, { LocationNames.SoutheastAsia, 160 }, { LocationNames.SouthIndia, 136 }, + { LocationNames.SpainCentral, 10 }, { LocationNames.SwedenCentral, 22 }, { LocationNames.SwedenSouth, 22 }, { LocationNames.SwitzerlandNorth, 12 }, { LocationNames.SwitzerlandWest, 16 }, + { LocationNames.TaiwanNorth, 193 }, + { LocationNames.TaiwanNorthwest, 193 }, { LocationNames.UAECentral, 118 }, { LocationNames.UAENorth, 120 }, { LocationNames.UKSouth, 10 }, @@ -5397,6 +5844,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 142 }, { LocationNames.AustraliaEast, 138 }, { LocationNames.AustraliaSoutheast, 134 }, + { LocationNames.AustriaEast, 116 }, { LocationNames.BrazilSouth, 304 }, { LocationNames.BrazilSoutheast, 304 }, { LocationNames.CanadaCentral, 210 }, @@ -5415,9 +5863,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 118 }, { LocationNames.FranceSouth, 106 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 130 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 122 }, { LocationNames.IsraelCentral, 28 }, { LocationNames.ItalyNorth, 116 }, @@ -5429,6 +5875,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 106 }, { LocationNames.MalaysiaSouth, 50 }, { LocationNames.MexicoCentral, 210 }, + { LocationNames.NewZealandNorth, 142 }, { LocationNames.NorthCentralUS, 218 }, { LocationNames.NorthEurope, 139 }, { LocationNames.NorwayEast, 146 }, @@ -5440,10 +5887,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 226 }, { LocationNames.SoutheastAsia, 50 }, { LocationNames.SouthIndia, 20 }, + { LocationNames.SpainCentral, 118 }, { LocationNames.SwedenCentral, 146 }, { LocationNames.SwedenSouth, 146 }, { LocationNames.SwitzerlandNorth, 116 }, { LocationNames.SwitzerlandWest, 112 }, + { LocationNames.TaiwanNorth, 84 }, + { LocationNames.TaiwanNorthwest, 84 }, { LocationNames.UAECentral, 28 }, { LocationNames.UAENorth, 28 }, { LocationNames.UKSouth, 126 }, @@ -5476,6 +5926,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 142 }, { LocationNames.AustraliaEast, 138 }, { LocationNames.AustraliaSoutheast, 148 }, + { LocationNames.AustriaEast, 150 }, { LocationNames.BrazilSouth, 172 }, { LocationNames.BrazilSoutheast, 172 }, { LocationNames.CanadaCentral, 64 }, @@ -5494,9 +5945,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 138 }, { LocationNames.FranceSouth, 148 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 153 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 148 }, { LocationNames.IsraelCentral, 244 }, { LocationNames.ItalyNorth, 150 }, @@ -5508,6 +5957,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 134 }, { LocationNames.MalaysiaSouth, 168 }, { LocationNames.MexicoCentral, 22 }, + { LocationNames.NewZealandNorth, 142 }, { LocationNames.NorthCentralUS, 50 }, { LocationNames.NorthEurope, 133 }, { LocationNames.NorwayEast, 163 }, @@ -5519,10 +5969,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 34 }, { LocationNames.SoutheastAsia, 168 }, { LocationNames.SouthIndia, 200 }, + { LocationNames.SpainCentral, 138 }, { LocationNames.SwedenCentral, 163 }, { LocationNames.SwedenSouth, 163 }, { LocationNames.SwitzerlandNorth, 150 }, { LocationNames.SwitzerlandWest, 147 }, + { LocationNames.TaiwanNorth, 148 }, + { LocationNames.TaiwanNorthwest, 148 }, { LocationNames.UAECentral, 244 }, { LocationNames.UAENorth, 244 }, { LocationNames.UKSouth, 136 }, @@ -5555,6 +6008,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 162 }, { LocationNames.AustraliaEast, 158 }, { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, { LocationNames.BrazilSouth, 182 }, { LocationNames.BrazilSoutheast, 182 }, { LocationNames.CanadaCentral, 57 }, @@ -5573,9 +6027,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 140 }, { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 148 }, { LocationNames.IsraelCentral, 236 }, { LocationNames.ItalyNorth, 154 }, @@ -5587,6 +6039,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 126 }, { LocationNames.MalaysiaSouth, 160 }, { LocationNames.MexicoCentral, 100 }, + { LocationNames.NewZealandNorth, 162 }, { LocationNames.NorthCentralUS, 44 }, { LocationNames.NorthEurope, 136 }, { LocationNames.NorwayEast, 164 }, @@ -5598,10 +6051,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 44 }, { LocationNames.SoutheastAsia, 160 }, { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, { LocationNames.SwedenCentral, 164 }, { LocationNames.SwedenSouth, 164 }, { LocationNames.SwitzerlandNorth, 154 }, { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, { LocationNames.UAECentral, 236 }, { LocationNames.UAENorth, 236 }, { LocationNames.UKSouth, 130 }, @@ -5621,7 +6077,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.WestIndia, 210 }, { LocationNames.WestUS, 22 }, { LocationNames.WestUS2, 0 }, - { LocationNames.WestUS3, 100 }, + { LocationNames.WestUS3, 32 }, { LocationNames.CentralUSEUAP, long.MaxValue }, { LocationNames.EastUS2EUAP, long.MaxValue }, } @@ -5634,6 +6090,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, 162 }, { LocationNames.AustraliaEast, 158 }, { LocationNames.AustraliaSoutheast, 168 }, + { LocationNames.AustriaEast, 154 }, { LocationNames.BrazilSouth, 182 }, { LocationNames.BrazilSoutheast, 182 }, { LocationNames.CanadaCentral, 57 }, @@ -5652,9 +6109,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, long.MaxValue }, { LocationNames.FranceCentral, 140 }, { LocationNames.FranceSouth, 146 }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, 154 }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, 148 }, { LocationNames.IsraelCentral, 236 }, { LocationNames.ItalyNorth, 154 }, @@ -5666,6 +6121,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, 126 }, { LocationNames.MalaysiaSouth, 160 }, { LocationNames.MexicoCentral, 100 }, + { LocationNames.NewZealandNorth, 162 }, { LocationNames.NorthCentralUS, 44 }, { LocationNames.NorthEurope, 136 }, { LocationNames.NorwayEast, 164 }, @@ -5677,10 +6133,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, 44 }, { LocationNames.SoutheastAsia, 160 }, { LocationNames.SouthIndia, 192 }, + { LocationNames.SpainCentral, 140 }, { LocationNames.SwedenCentral, 164 }, { LocationNames.SwedenSouth, 164 }, { LocationNames.SwitzerlandNorth, 154 }, { LocationNames.SwitzerlandWest, 146 }, + { LocationNames.TaiwanNorth, 140 }, + { LocationNames.TaiwanNorthwest, 140 }, { LocationNames.UAECentral, 236 }, { LocationNames.UAENorth, 236 }, { LocationNames.UKSouth, 130 }, @@ -5699,7 +6158,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.WestEurope, 142 }, { LocationNames.WestIndia, 210 }, { LocationNames.WestUS, 22 }, - { LocationNames.WestUS2, 100 }, + { LocationNames.WestUS2, 32 }, { LocationNames.WestUS3, 0 }, { LocationNames.CentralUSEUAP, long.MaxValue }, { LocationNames.EastUS2EUAP, long.MaxValue }, @@ -5713,6 +6172,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -5731,9 +6191,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, 255 }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -5745,6 +6203,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -5756,10 +6215,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, @@ -5792,6 +6254,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.AustraliaCentral2, long.MaxValue }, { LocationNames.AustraliaEast, long.MaxValue }, { LocationNames.AustraliaSoutheast, long.MaxValue }, + { LocationNames.AustriaEast, long.MaxValue }, { LocationNames.BrazilSouth, long.MaxValue }, { LocationNames.BrazilSoutheast, long.MaxValue }, { LocationNames.CanadaCentral, long.MaxValue }, @@ -5810,9 +6273,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.EastUSSLV, 255 }, { LocationNames.FranceCentral, long.MaxValue }, { LocationNames.FranceSouth, long.MaxValue }, - { LocationNames.GermanyCentral, long.MaxValue }, { LocationNames.GermanyNorth, long.MaxValue }, - { LocationNames.GermanyNortheast, long.MaxValue }, { LocationNames.GermanyWestCentral, long.MaxValue }, { LocationNames.IsraelCentral, long.MaxValue }, { LocationNames.ItalyNorth, long.MaxValue }, @@ -5824,6 +6285,7 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.KoreaSouth, long.MaxValue }, { LocationNames.MalaysiaSouth, long.MaxValue }, { LocationNames.MexicoCentral, long.MaxValue }, + { LocationNames.NewZealandNorth, long.MaxValue }, { LocationNames.NorthCentralUS, long.MaxValue }, { LocationNames.NorthEurope, long.MaxValue }, { LocationNames.NorwayEast, long.MaxValue }, @@ -5835,10 +6297,13 @@ public static List GeneratePreferredRegionList(string sourceRegion) { LocationNames.SouthCentralUS, long.MaxValue }, { LocationNames.SoutheastAsia, long.MaxValue }, { LocationNames.SouthIndia, long.MaxValue }, + { LocationNames.SpainCentral, long.MaxValue }, { LocationNames.SwedenCentral, long.MaxValue }, { LocationNames.SwedenSouth, long.MaxValue }, { LocationNames.SwitzerlandNorth, long.MaxValue }, { LocationNames.SwitzerlandWest, long.MaxValue }, + { LocationNames.TaiwanNorth, long.MaxValue }, + { LocationNames.TaiwanNorthwest, long.MaxValue }, { LocationNames.UAECentral, long.MaxValue }, { LocationNames.UAENorth, long.MaxValue }, { LocationNames.UKSouth, long.MaxValue }, diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs index fe3a2042db..4e2072deb4 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestNameValueCollection.cs @@ -37,7 +37,9 @@ internal class RequestNameValueCollection : INameValueCollection private NameValueCollection nameValueCollection = null; public string A_IM { get; set; } + public string ActivityId { get; set; } public string AddResourcePropertiesToResponse { get; set; } + public string AllowDocumentReadsInOfflineRegion { get; set; } public string AllowRestoreParamsUpdate { get; set; } public string AllowTentativeWrites { get; set; } public string Authorization { get; set; } @@ -50,6 +52,7 @@ internal class RequestNameValueCollection : INameValueCollection public string CanThrottle { get; set; } public string ChangeFeedStartFullFidelityIfNoneMatch { get; set; } public string ChangeFeedWireFormatVersion { get; set; } + public string ClientIpAddress { get; set; } public string ClientRetryAttemptCount { get; set; } public string CollectionChildResourceContentLimitInKB { get; set; } public string CollectionChildResourceNameLimitInBytes { get; set; } @@ -65,6 +68,8 @@ internal class RequestNameValueCollection : INameValueCollection public string DisableRUPerMinuteUsage { get; set; } public string EffectivePartitionKey { get; set; } public string EmitVerboseTracesInQuery { get; set; } + public string EnableConflictResolutionPolicyUpdate { get; set; } + public string EnableCrossPartitionQuery { get; set; } public string EnableDynamicRidRangeAllocation { get; set; } public string EnableLogging { get; set; } public string EnableLowPrecisionOrderBy { get; set; } @@ -96,6 +101,7 @@ internal class RequestNameValueCollection : INameValueCollection public string IsBatchOrdered { get; set; } public string IsCassandraAlterTypeRequest { get; set; } public string IsClientEncrypted { get; set; } + public string IsContinuationExpected { get; set; } public string IsFanoutRequest { get; set; } public string IsInternalServerlessRequest { get; set; } public string IsMaterializedViewBuild { get; set; } @@ -103,6 +109,7 @@ internal class RequestNameValueCollection : INameValueCollection public string IsMigratedFixedCollection { get; set; } public string IsOfferStorageRefreshRequest { get; set; } public string IsReadOnlyScript { get; set; } + public string IsRequestNotAuthorized { get; set; } public string IsRetriedWriteRequest { get; set; } public string IsRUPerGBEnforcementRequest { get; set; } public string IsServerlessStorageRefreshRequest { get; set; } @@ -118,6 +125,7 @@ internal class RequestNameValueCollection : INameValueCollection public string OfferReplaceRURedistribution { get; set; } public string OptimisticDirectExecute { get; set; } public string PageSize { get; set; } + public string ParallelizeCrossPartitionQuery { get; set; } public string PartitionCount { get; set; } public string PartitionKey { get; set; } public string PartitionKeyRangeId { get; set; } @@ -126,6 +134,7 @@ internal class RequestNameValueCollection : INameValueCollection public string PopulateByokEncryptionProgress { get; set; } public string PopulateCapacityType { get; set; } public string PopulateCollectionThroughputInfo { get; set; } + public string PopulateCurrentPartitionThroughputInfo { get; set; } public string PopulateHighestTentativeWriteLLSN { get; set; } public string PopulateIndexMetrics { get; set; } public string PopulateIndexMetricsV2 { get; set; } @@ -149,6 +158,7 @@ internal class RequestNameValueCollection : INameValueCollection public string PriorityLevel { get; set; } public string ProfileRequest { get; set; } public string PruneCollectionSchemas { get; set; } + public string QueryVersion { get; set; } public string RbacAction { get; set; } public string RbacResource { get; set; } public string RbacUserId { get; set; } @@ -179,8 +189,10 @@ internal class RequestNameValueCollection : INameValueCollection public string SkipAdjustThroughputFractionsForOfferReplace { get; set; } public string SkipRefreshDatabaseAccountConfigs { get; set; } public string SourceCollectionIfMatch { get; set; } + public string SqlQueryForPartitionKeyExtraction { get; set; } public string StartEpk { get; set; } public string StartId { get; set; } + public string SupportedQueryFeatures { get; set; } public string SupportedSerializationFormats { get; set; } public string SupportSpatialLegacyCoordinates { get; set; } public string SystemDocumentType { get; set; } @@ -227,6 +239,23 @@ public RequestNameValueCollection(IDictionary requestHeaders) } } + /// + /// Only process known headers. + /// + /// + /// Non thread safe. Does not support requestHeaders modification while running this method. + /// + public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnownHeadersOnly(IDictionary requestHeaders) + { + RequestNameValueCollection requestNameValueCollection = new RequestNameValueCollection(); + foreach (KeyValuePair keyValue in requestHeaders) + { + requestNameValueCollection.UpdateHelper(keyValue.Key, value: keyValue.Value, throwIfAlreadyExists: false, ignoreNotCommonHeaders: true); + } + + return requestNameValueCollection; + } + /// /// Only process known headers. Ignores nameValueCollection changes by switching to per field assignment if InvalidOperationException happens while iterating over the keys. /// @@ -410,12 +439,23 @@ public static RequestNameValueCollection BuildRequestNameValueCollectionWithKnow requestNameValueCollection.OptimisticDirectExecute = nameValueCollection[HttpConstants.HttpHeaders.OptimisticDirectExecute]; requestNameValueCollection.PopulateMinGLSNForDocumentOperations = nameValueCollection[WFConstants.BackendHeaders.PopulateMinGLSNForDocumentOperations]; requestNameValueCollection.PopulateHighestTentativeWriteLLSN = nameValueCollection[WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN]; + requestNameValueCollection.PopulateCapacityType = nameValueCollection[WFConstants.BackendHeaders.PopulateCapacityType]; requestNameValueCollection.TraceParent = nameValueCollection[HttpConstants.HttpHeaders.TraceParent]; requestNameValueCollection.TraceState = nameValueCollection[HttpConstants.HttpHeaders.TraceState]; - requestNameValueCollection.PopulateCapacityType = nameValueCollection[WFConstants.BackendHeaders.PopulateCapacityType]; + requestNameValueCollection.EnableConflictResolutionPolicyUpdate = nameValueCollection[HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate]; + requestNameValueCollection.ClientIpAddress = nameValueCollection[WFConstants.BackendHeaders.ClientIpAddress]; + requestNameValueCollection.IsRequestNotAuthorized = nameValueCollection[WFConstants.BackendHeaders.IsRequestNotAuthorized]; + requestNameValueCollection.PopulateCurrentPartitionThroughputInfo = nameValueCollection[WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo]; requestNameValueCollection.IfMatch = nameValueCollection[HttpConstants.HttpHeaders.IfMatch]; requestNameValueCollection.NoRetryOn449StatusCode = nameValueCollection[HttpConstants.HttpHeaders.NoRetryOn449StatusCode]; requestNameValueCollection.SkipAdjustThroughputFractionsForOfferReplace = nameValueCollection[HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace]; + requestNameValueCollection.SqlQueryForPartitionKeyExtraction = nameValueCollection[HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction]; + requestNameValueCollection.EnableCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.EnableCrossPartitionQuery]; + requestNameValueCollection.IsContinuationExpected = nameValueCollection[HttpConstants.HttpHeaders.IsContinuationExpected]; + requestNameValueCollection.ParallelizeCrossPartitionQuery = nameValueCollection[HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery]; + requestNameValueCollection.SupportedQueryFeatures = nameValueCollection[HttpConstants.HttpHeaders.SupportedQueryFeatures]; + requestNameValueCollection.QueryVersion = nameValueCollection[HttpConstants.HttpHeaders.QueryVersion]; + requestNameValueCollection.ActivityId = nameValueCollection[HttpConstants.HttpHeaders.ActivityId]; } return requestNameValueCollection; @@ -453,7 +493,9 @@ public void Clear() } this.A_IM = null; + this.ActivityId = null; this.AddResourcePropertiesToResponse = null; + this.AllowDocumentReadsInOfflineRegion = null; this.AllowRestoreParamsUpdate = null; this.AllowTentativeWrites = null; this.Authorization = null; @@ -466,6 +508,7 @@ public void Clear() this.CanThrottle = null; this.ChangeFeedStartFullFidelityIfNoneMatch = null; this.ChangeFeedWireFormatVersion = null; + this.ClientIpAddress = null; this.ClientRetryAttemptCount = null; this.CollectionChildResourceContentLimitInKB = null; this.CollectionChildResourceNameLimitInBytes = null; @@ -481,6 +524,8 @@ public void Clear() this.DisableRUPerMinuteUsage = null; this.EffectivePartitionKey = null; this.EmitVerboseTracesInQuery = null; + this.EnableConflictResolutionPolicyUpdate = null; + this.EnableCrossPartitionQuery = null; this.EnableDynamicRidRangeAllocation = null; this.EnableLogging = null; this.EnableLowPrecisionOrderBy = null; @@ -512,6 +557,7 @@ public void Clear() this.IsBatchOrdered = null; this.IsCassandraAlterTypeRequest = null; this.IsClientEncrypted = null; + this.IsContinuationExpected = null; this.IsFanoutRequest = null; this.IsInternalServerlessRequest = null; this.IsMaterializedViewBuild = null; @@ -519,6 +565,7 @@ public void Clear() this.IsMigratedFixedCollection = null; this.IsOfferStorageRefreshRequest = null; this.IsReadOnlyScript = null; + this.IsRequestNotAuthorized = null; this.IsRetriedWriteRequest = null; this.IsRUPerGBEnforcementRequest = null; this.IsServerlessStorageRefreshRequest = null; @@ -534,6 +581,7 @@ public void Clear() this.OfferReplaceRURedistribution = null; this.OptimisticDirectExecute = null; this.PageSize = null; + this.ParallelizeCrossPartitionQuery = null; this.PartitionCount = null; this.PartitionKey = null; this.PartitionKeyRangeId = null; @@ -542,6 +590,7 @@ public void Clear() this.PopulateByokEncryptionProgress = null; this.PopulateCapacityType = null; this.PopulateCollectionThroughputInfo = null; + this.PopulateCurrentPartitionThroughputInfo = null; this.PopulateHighestTentativeWriteLLSN = null; this.PopulateIndexMetrics = null; this.PopulateIndexMetricsV2 = null; @@ -565,6 +614,7 @@ public void Clear() this.PriorityLevel = null; this.ProfileRequest = null; this.PruneCollectionSchemas = null; + this.QueryVersion = null; this.RbacAction = null; this.RbacResource = null; this.RbacUserId = null; @@ -595,8 +645,10 @@ public void Clear() this.SkipAdjustThroughputFractionsForOfferReplace = null; this.SkipRefreshDatabaseAccountConfigs = null; this.SourceCollectionIfMatch = null; + this.SqlQueryForPartitionKeyExtraction = null; this.StartEpk = null; this.StartId = null; + this.SupportedQueryFeatures = null; this.SupportedSerializationFormats = null; this.SupportSpatialLegacyCoordinates = null; this.SystemDocumentType = null; @@ -630,7 +682,9 @@ public INameValueCollection Clone() RequestNameValueCollection cloneHeaders = new RequestNameValueCollection() { A_IM = this.A_IM, + ActivityId = this.ActivityId, AddResourcePropertiesToResponse = this.AddResourcePropertiesToResponse, + AllowDocumentReadsInOfflineRegion = this.AllowDocumentReadsInOfflineRegion, AllowRestoreParamsUpdate = this.AllowRestoreParamsUpdate, AllowTentativeWrites = this.AllowTentativeWrites, Authorization = this.Authorization, @@ -643,6 +697,7 @@ public INameValueCollection Clone() CanThrottle = this.CanThrottle, ChangeFeedStartFullFidelityIfNoneMatch = this.ChangeFeedStartFullFidelityIfNoneMatch, ChangeFeedWireFormatVersion = this.ChangeFeedWireFormatVersion, + ClientIpAddress = this.ClientIpAddress, ClientRetryAttemptCount = this.ClientRetryAttemptCount, CollectionChildResourceContentLimitInKB = this.CollectionChildResourceContentLimitInKB, CollectionChildResourceNameLimitInBytes = this.CollectionChildResourceNameLimitInBytes, @@ -658,6 +713,8 @@ public INameValueCollection Clone() DisableRUPerMinuteUsage = this.DisableRUPerMinuteUsage, EffectivePartitionKey = this.EffectivePartitionKey, EmitVerboseTracesInQuery = this.EmitVerboseTracesInQuery, + EnableConflictResolutionPolicyUpdate = this.EnableConflictResolutionPolicyUpdate, + EnableCrossPartitionQuery = this.EnableCrossPartitionQuery, EnableDynamicRidRangeAllocation = this.EnableDynamicRidRangeAllocation, EnableLogging = this.EnableLogging, EnableLowPrecisionOrderBy = this.EnableLowPrecisionOrderBy, @@ -689,6 +746,7 @@ public INameValueCollection Clone() IsBatchOrdered = this.IsBatchOrdered, IsCassandraAlterTypeRequest = this.IsCassandraAlterTypeRequest, IsClientEncrypted = this.IsClientEncrypted, + IsContinuationExpected = this.IsContinuationExpected, IsFanoutRequest = this.IsFanoutRequest, IsInternalServerlessRequest = this.IsInternalServerlessRequest, IsMaterializedViewBuild = this.IsMaterializedViewBuild, @@ -696,6 +754,7 @@ public INameValueCollection Clone() IsMigratedFixedCollection = this.IsMigratedFixedCollection, IsOfferStorageRefreshRequest = this.IsOfferStorageRefreshRequest, IsReadOnlyScript = this.IsReadOnlyScript, + IsRequestNotAuthorized = this.IsRequestNotAuthorized, IsRetriedWriteRequest = this.IsRetriedWriteRequest, IsRUPerGBEnforcementRequest = this.IsRUPerGBEnforcementRequest, IsServerlessStorageRefreshRequest = this.IsServerlessStorageRefreshRequest, @@ -711,6 +770,7 @@ public INameValueCollection Clone() OfferReplaceRURedistribution = this.OfferReplaceRURedistribution, OptimisticDirectExecute = this.OptimisticDirectExecute, PageSize = this.PageSize, + ParallelizeCrossPartitionQuery = this.ParallelizeCrossPartitionQuery, PartitionCount = this.PartitionCount, PartitionKey = this.PartitionKey, PartitionKeyRangeId = this.PartitionKeyRangeId, @@ -719,6 +779,7 @@ public INameValueCollection Clone() PopulateByokEncryptionProgress = this.PopulateByokEncryptionProgress, PopulateCapacityType = this.PopulateCapacityType, PopulateCollectionThroughputInfo = this.PopulateCollectionThroughputInfo, + PopulateCurrentPartitionThroughputInfo = this.PopulateCurrentPartitionThroughputInfo, PopulateHighestTentativeWriteLLSN = this.PopulateHighestTentativeWriteLLSN, PopulateIndexMetrics = this.PopulateIndexMetrics, PopulateIndexMetricsV2 = this.PopulateIndexMetricsV2, @@ -742,6 +803,7 @@ public INameValueCollection Clone() PriorityLevel = this.PriorityLevel, ProfileRequest = this.ProfileRequest, PruneCollectionSchemas = this.PruneCollectionSchemas, + QueryVersion = this.QueryVersion, RbacAction = this.RbacAction, RbacResource = this.RbacResource, RbacUserId = this.RbacUserId, @@ -772,8 +834,10 @@ public INameValueCollection Clone() SkipAdjustThroughputFractionsForOfferReplace = this.SkipAdjustThroughputFractionsForOfferReplace, SkipRefreshDatabaseAccountConfigs = this.SkipRefreshDatabaseAccountConfigs, SourceCollectionIfMatch = this.SourceCollectionIfMatch, + SqlQueryForPartitionKeyExtraction = this.SqlQueryForPartitionKeyExtraction, StartEpk = this.StartEpk, StartId = this.StartId, + SupportedQueryFeatures = this.SupportedQueryFeatures, SupportedSerializationFormats = this.SupportedSerializationFormats, SupportSpatialLegacyCoordinates = this.SupportSpatialLegacyCoordinates, SystemDocumentType = this.SystemDocumentType, @@ -1488,6 +1552,10 @@ public IEnumerable Keys() { yield return WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN; } + if (this.PopulateCapacityType != null) + { + yield return WFConstants.BackendHeaders.PopulateCapacityType; + } if (this.TraceParent != null) { yield return HttpConstants.HttpHeaders.TraceParent; @@ -1496,9 +1564,25 @@ public IEnumerable Keys() { yield return HttpConstants.HttpHeaders.TraceState; } - if (this.PopulateCapacityType != null) + if (this.EnableConflictResolutionPolicyUpdate != null) { - yield return WFConstants.BackendHeaders.PopulateCapacityType; + yield return HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate; + } + if (this.ClientIpAddress != null) + { + yield return WFConstants.BackendHeaders.ClientIpAddress; + } + if (this.IsRequestNotAuthorized != null) + { + yield return WFConstants.BackendHeaders.IsRequestNotAuthorized; + } + if (this.AllowDocumentReadsInOfflineRegion != null) + { + yield return HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion; + } + if (this.PopulateCurrentPartitionThroughputInfo != null) + { + yield return WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo; } if (this.IfMatch != null) { @@ -1512,6 +1596,34 @@ public IEnumerable Keys() { yield return HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace; } + if (this.SqlQueryForPartitionKeyExtraction != null) + { + yield return HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction; + } + if (this.EnableCrossPartitionQuery != null) + { + yield return HttpConstants.HttpHeaders.EnableCrossPartitionQuery; + } + if (this.IsContinuationExpected != null) + { + yield return HttpConstants.HttpHeaders.IsContinuationExpected; + } + if (this.ParallelizeCrossPartitionQuery != null) + { + yield return HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery; + } + if (this.SupportedQueryFeatures != null) + { + yield return HttpConstants.HttpHeaders.SupportedQueryFeatures; + } + if (this.QueryVersion != null) + { + yield return HttpConstants.HttpHeaders.QueryVersion; + } + if (this.ActivityId != null) + { + yield return HttpConstants.HttpHeaders.ActivityId; + } if (this.notCommonHeaders != null) { @@ -2190,6 +2302,10 @@ public NameValueCollection ToNameValueCollection() { this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateHighestTentativeWriteLLSN, this.PopulateHighestTentativeWriteLLSN); } + if (this.PopulateCapacityType != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCapacityType, this.PopulateCapacityType); + } if (this.TraceParent != null) { this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceParent, this.TraceParent); @@ -2198,9 +2314,25 @@ public NameValueCollection ToNameValueCollection() { this.nameValueCollection.Add(HttpConstants.HttpHeaders.TraceState, this.TraceState); } - if (this.PopulateCapacityType != null) + if (this.EnableConflictResolutionPolicyUpdate != null) { - this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCapacityType, this.PopulateCapacityType); + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, this.EnableConflictResolutionPolicyUpdate); + } + if (this.ClientIpAddress != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.ClientIpAddress, this.ClientIpAddress); + } + if (this.IsRequestNotAuthorized != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.IsRequestNotAuthorized, this.IsRequestNotAuthorized); + } + if (this.AllowDocumentReadsInOfflineRegion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, this.AllowDocumentReadsInOfflineRegion); + } + if (this.PopulateCurrentPartitionThroughputInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, this.PopulateCurrentPartitionThroughputInfo); } if (this.IfMatch != null) { @@ -2214,6 +2346,34 @@ public NameValueCollection ToNameValueCollection() { this.nameValueCollection.Add(HttpConstants.HttpHeaders.SkipAdjustThroughputFractionsForOfferReplace, this.SkipAdjustThroughputFractionsForOfferReplace); } + if (this.SqlQueryForPartitionKeyExtraction != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, this.SqlQueryForPartitionKeyExtraction); + } + if (this.EnableCrossPartitionQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, this.EnableCrossPartitionQuery); + } + if (this.IsContinuationExpected != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.IsContinuationExpected, this.IsContinuationExpected); + } + if (this.ParallelizeCrossPartitionQuery != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, this.ParallelizeCrossPartitionQuery); + } + if (this.SupportedQueryFeatures != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.SupportedQueryFeatures, this.SupportedQueryFeatures); + } + if (this.QueryVersion != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.QueryVersion, this.QueryVersion); + } + if (this.ActivityId != null) + { + this.nameValueCollection.Add(HttpConstants.HttpHeaders.ActivityId, this.ActivityId); + } if (this.notCommonHeaders != null) { foreach (KeyValuePair keyValuePair in this.notCommonHeaders) @@ -2300,6 +2460,14 @@ public string Get(string key) break; case 11: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) + { + return this.EndId; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) + { + return this.TraceParent; + } if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) { return this.EndId; @@ -2422,6 +2590,10 @@ public string Get(string key) { return this.NoRetryOn449StatusCode; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + return this.ActivityId; + } if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) { return this.CanThrottle; @@ -2442,6 +2614,11 @@ public string Get(string key) return this.NoRetryOn449StatusCode; } + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ActivityId; + } + break; case 17: if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) @@ -2723,6 +2900,10 @@ public string Get(string key) { return this.ResourceTypes; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) + { + return this.QueryVersion; + } if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) { return this.ResourceSchemaName; @@ -2753,6 +2934,11 @@ public string Get(string key) return this.ResourceTypes; } + if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.QueryVersion; + } + break; case 26: if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) @@ -2867,6 +3053,13 @@ public string Get(string key) return this.UseSystemBudget; } + break; + case 29: + if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ClientIpAddress; + } + break; case 30: if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) @@ -3224,6 +3417,10 @@ public string Get(string key) { return this.PruneCollectionSchemas; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) + { + return this.SupportedQueryFeatures; + } if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) { return this.PostTriggerInclude; @@ -3259,6 +3456,11 @@ public string Get(string key) return this.PruneCollectionSchemas; } + if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SupportedQueryFeatures; + } + break; case 37: if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) @@ -3277,6 +3479,10 @@ public string Get(string key) { return this.BuilderClientIdentifier; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) + { + return this.IsRequestNotAuthorized; + } if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) { return this.EnableLogging; @@ -3297,6 +3503,11 @@ public string Get(string key) return this.BuilderClientIdentifier; } + if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsRequestNotAuthorized; + } + break; case 38: if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) @@ -3409,6 +3620,10 @@ public string Get(string key) { return this.ChangeFeedWireFormatVersion; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) + { + return this.EnableCrossPartitionQuery; + } if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) { return this.MergeCheckPointGLSN; @@ -3424,6 +3639,11 @@ public string Get(string key) return this.ChangeFeedWireFormatVersion; } + if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableCrossPartitionQuery; + } + break; case 43: if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) @@ -3481,6 +3701,10 @@ public string Get(string key) { return this.PopulateOldestActiveSchemaId; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) + { + return this.IsContinuationExpected; + } if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) { return this.ContentSerializationFormat; @@ -3491,6 +3715,11 @@ public string Get(string key) return this.PopulateOldestActiveSchemaId; } + if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) + { + return this.IsContinuationExpected; + } + break; case 45: if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) @@ -3701,11 +3930,24 @@ public string Get(string key) break; case 52: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) + { + return this.OfferReplaceRURedistribution; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) + { + return this.ParallelizeCrossPartitionQuery; + } if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) { return this.OfferReplaceRURedistribution; } + if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + return this.ParallelizeCrossPartitionQuery; + } + break; case 53: if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) @@ -3745,6 +3987,10 @@ public string Get(string key) { return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) + { + return this.PopulateCurrentPartitionThroughputInfo; + } if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) { return this.IncludePhysicalPartitionThroughputInfo; @@ -3755,13 +4001,31 @@ public string Get(string key) return this.IsMaterializedViewSourceSchemaReplaceBatchRequest; } + if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PopulateCurrentPartitionThroughputInfo; + } + break; case 55: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) + { + return this.UpdateOfferStateToRestorePending; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) + { + return this.SqlQueryForPartitionKeyExtraction; + } if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) { return this.UpdateOfferStateToRestorePending; } + if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) + { + return this.SqlQueryForPartitionKeyExtraction; + } + break; case 56: if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) @@ -3807,11 +4071,33 @@ public string Get(string key) break; case 59: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) + { + return this.UpdateMaxThroughputEverProvisioned; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) + { + return this.EnableConflictResolutionPolicyUpdate; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) + { + return this.AllowDocumentReadsInOfflineRegion; + } if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) { return this.UpdateMaxThroughputEverProvisioned; } + if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + return this.EnableConflictResolutionPolicyUpdate; + } + + if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) + { + return this.AllowDocumentReadsInOfflineRegion; + } + break; case 61: if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) @@ -3977,6 +4263,26 @@ public void UpdateHelper( } break; case 11: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EndId, key)) + { + if (throwIfAlreadyExists && this.EndId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EndId = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.TraceParent, key)) + { + if (throwIfAlreadyExists && this.TraceParent != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.TraceParent = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.EndId, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.EndId != null) @@ -4237,6 +4543,16 @@ public void UpdateHelper( this.NoRetryOn449StatusCode = value; return; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ActivityId, key)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.CanThrottle, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.CanThrottle != null) @@ -4277,6 +4593,16 @@ public void UpdateHelper( this.NoRetryOn449StatusCode = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.ActivityId, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ActivityId != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ActivityId = value; + return; + } break; case 17: if (object.ReferenceEquals(HttpConstants.HttpHeaders.Continuation, key)) @@ -4885,6 +5211,16 @@ public void UpdateHelper( this.ResourceTypes = value; return; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.QueryVersion, key)) + { + if (throwIfAlreadyExists && this.QueryVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryVersion = value; + return; + } if (string.Equals(WFConstants.BackendHeaders.ResourceSchemaName, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.ResourceSchemaName != null) @@ -4945,6 +5281,16 @@ public void UpdateHelper( this.ResourceTypes = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.QueryVersion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.QueryVersion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.QueryVersion = value; + return; + } break; case 26: if (object.ReferenceEquals(WFConstants.BackendHeaders.CollectionPartitionIndex, key)) @@ -5192,6 +5538,18 @@ public void UpdateHelper( return; } break; + case 29: + if (string.Equals(WFConstants.BackendHeaders.ClientIpAddress, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ClientIpAddress != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ClientIpAddress = value; + return; + } + break; case 30: if (object.ReferenceEquals(HttpConstants.HttpHeaders.ResourceTokenExpiry, key)) { @@ -5975,6 +6333,16 @@ public void UpdateHelper( this.PruneCollectionSchemas = value; return; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key)) + { + if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedQueryFeatures = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.PostTriggerInclude, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.PostTriggerInclude != null) @@ -6045,6 +6413,16 @@ public void UpdateHelper( this.PruneCollectionSchemas = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.SupportedQueryFeatures, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SupportedQueryFeatures != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SupportedQueryFeatures = value; + return; + } break; case 37: if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableLogging, key)) @@ -6087,6 +6465,16 @@ public void UpdateHelper( this.BuilderClientIdentifier = value; return; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key)) + { + if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRequestNotAuthorized = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.EnableLogging, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.EnableLogging != null) @@ -6127,6 +6515,16 @@ public void UpdateHelper( this.BuilderClientIdentifier = value; return; } + if (string.Equals(WFConstants.BackendHeaders.IsRequestNotAuthorized, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsRequestNotAuthorized != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsRequestNotAuthorized = value; + return; + } break; case 38: if (object.ReferenceEquals(HttpConstants.HttpHeaders.MigrateOfferToAutopilot, key)) @@ -6367,6 +6765,16 @@ public void UpdateHelper( this.ChangeFeedWireFormatVersion = value; return; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key)) + { + if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableCrossPartitionQuery = value; + return; + } if (string.Equals(WFConstants.BackendHeaders.MergeCheckPointGLSN, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.MergeCheckPointGLSN != null) @@ -6397,6 +6805,16 @@ public void UpdateHelper( this.ChangeFeedWireFormatVersion = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.EnableCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableCrossPartitionQuery = value; + return; + } break; case 43: if (object.ReferenceEquals(HttpConstants.HttpHeaders.DisableRUPerMinuteUsage, key)) @@ -6521,6 +6939,16 @@ public void UpdateHelper( this.PopulateOldestActiveSchemaId = value; return; } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsContinuationExpected, key)) + { + if (throwIfAlreadyExists && this.IsContinuationExpected != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsContinuationExpected = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.ContentSerializationFormat, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.ContentSerializationFormat != null) @@ -6541,6 +6969,16 @@ public void UpdateHelper( this.PopulateOldestActiveSchemaId = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.IsContinuationExpected, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.IsContinuationExpected != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.IsContinuationExpected = value; + return; + } break; case 45: if (object.ReferenceEquals(HttpConstants.HttpHeaders.ChangeFeedStartFullFidelityIfNoneMatch, key)) @@ -6987,6 +7425,26 @@ public void UpdateHelper( } break; case 52: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key)) + { + if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.OfferReplaceRURedistribution = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key)) + { + if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ParallelizeCrossPartitionQuery = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.OfferReplaceRURedistribution, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.OfferReplaceRURedistribution != null) @@ -6997,6 +7455,16 @@ public void UpdateHelper( this.OfferReplaceRURedistribution = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.ParallelizeCrossPartitionQuery, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.ParallelizeCrossPartitionQuery != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.ParallelizeCrossPartitionQuery = value; + return; + } break; case 53: if (object.ReferenceEquals(HttpConstants.HttpHeaders.IsRUPerGBEnforcementRequest, key)) @@ -7081,6 +7549,16 @@ public void UpdateHelper( this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; return; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCurrentPartitionThroughputInfo = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.IncludePhysicalPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.IncludePhysicalPartitionThroughputInfo != null) @@ -7101,8 +7579,38 @@ public void UpdateHelper( this.IsMaterializedViewSourceSchemaReplaceBatchRequest = value; return; } + if (string.Equals(WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PopulateCurrentPartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PopulateCurrentPartitionThroughputInfo = value; + return; + } break; case 55: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key)) + { + if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateOfferStateToRestorePending = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key)) + { + if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SqlQueryForPartitionKeyExtraction = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.UpdateOfferStateToRestorePending, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.UpdateOfferStateToRestorePending != null) @@ -7113,6 +7621,16 @@ public void UpdateHelper( this.UpdateOfferStateToRestorePending = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.SqlQueryForPartitionKeyExtraction, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.SqlQueryForPartitionKeyExtraction != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SqlQueryForPartitionKeyExtraction = value; + return; + } break; case 56: if (string.Equals(WFConstants.BackendHeaders.CollectionChildResourceContentLimitInKB, key, StringComparison.OrdinalIgnoreCase)) @@ -7201,6 +7719,36 @@ public void UpdateHelper( } break; case 59: + if (object.ReferenceEquals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key)) + { + if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.UpdateMaxThroughputEverProvisioned = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key)) + { + if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableConflictResolutionPolicyUpdate = value; + return; + } + if (object.ReferenceEquals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key)) + { + if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowDocumentReadsInOfflineRegion = value; + return; + } if (string.Equals(HttpConstants.HttpHeaders.UpdateMaxThroughputEverProvisioned, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.UpdateMaxThroughputEverProvisioned != null) @@ -7211,6 +7759,26 @@ public void UpdateHelper( this.UpdateMaxThroughputEverProvisioned = value; return; } + if (string.Equals(HttpConstants.HttpHeaders.EnableConflictResolutionPolicyUpdate, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.EnableConflictResolutionPolicyUpdate != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.EnableConflictResolutionPolicyUpdate = value; + return; + } + if (string.Equals(HttpConstants.HttpHeaders.AllowDocumentReadsInOfflineRegion, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.AllowDocumentReadsInOfflineRegion != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.AllowDocumentReadsInOfflineRegion = value; + return; + } break; case 61: if (string.Equals(HttpConstants.HttpHeaders.IsServerlessStorageRefreshRequest, key, StringComparison.OrdinalIgnoreCase)) diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs b/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs index 7700911c57..a473107bed 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestOptions.cs @@ -555,6 +555,16 @@ sealed class RequestOptions /// internal bool PopulateRestoreStatus { get; set; } + /// + /// Gets or sets the for document create requests in the Azure Cosmos DB service. + /// + /// + /// + /// PopulateCapacityType is used to return the capacity type of the request. + /// + /// + internal bool PopulateCapacityType { get; set; } + /// /// Gets or sets exclude system properties. /// ExcludeSystemProperties indicates whether system properties diff --git a/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs b/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs index 072de737bb..92cdbfd7de 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RequestRetryUtility.cs @@ -64,85 +64,104 @@ public static async Task ProcessRequestAsync= minBackoffForInBackoffCallback.Value) - { - Stopwatch stopwatch = new Stopwatch(); - try + return response; + } + + TimeSpan backoffTime = shouldRetry.BackoffTime; + if (inBackoffAlternateCallbackMethod != null && backoffTime >= minBackoffForInBackoffCallback.Value) { - stopwatch.Start(); - IRetriableResponse inBackoffResponse = await inBackoffAlternateCallbackMethod(); - stopwatch.Stop(); - ShouldRetryResult shouldRetryInBackOff = null; - Debug.Assert(inBackoffResponse != null); - if (!policy.TryHandleResponseSynchronously( - request: request, - response: inBackoffResponse, - exception: null, - shouldRetryResult: out shouldRetryInBackOff)) + Stopwatch stopwatch = new Stopwatch(); + try { - shouldRetryInBackOff = await policy.ShouldRetryAsync( + stopwatch.Start(); + IRetriableResponse inBackoffResponse = await inBackoffAlternateCallbackMethod(); + stopwatch.Stop(); + ShouldRetryResult shouldRetryInBackOff = null; + Debug.Assert(inBackoffResponse != null); + if (!policy.TryHandleResponseSynchronously( request: request, response: inBackoffResponse, exception: null, - cancellationToken: cancellationToken); - } + shouldRetryResult: out shouldRetryInBackOff)) + { + shouldRetryInBackOff = await policy.ShouldRetryAsync( + request: request, + response: inBackoffResponse, + exception: null, + cancellationToken: cancellationToken); + } + + if (!shouldRetryInBackOff.ShouldRetry) + { + return inBackoffResponse; + } - if (!shouldRetryInBackOff.ShouldRetry) + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with response, proceeding with retry. Time taken: {0}ms", stopwatch.ElapsedMilliseconds); + } + catch (Exception ex) { - return inBackoffResponse; + stopwatch.Stop(); + DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), stopwatch.ElapsedMilliseconds); } - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with response, proceeding with retry. Time taken: {0}ms", stopwatch.ElapsedMilliseconds); + backoffTime = shouldRetry.BackoffTime > stopwatch.Elapsed ? shouldRetry.BackoffTime - stopwatch.Elapsed : TimeSpan.Zero; } - catch (Exception ex) + + if (backoffTime != TimeSpan.Zero) { - stopwatch.Stop(); - DefaultTrace.TraceInformation("Failed inBackoffAlternateCallback with {0}, proceeding with retry. Time taken: {1}ms", ex.ToString(), stopwatch.ElapsedMilliseconds); + await Task.Delay(backoffTime, cancellationToken); } - backoffTime = shouldRetry.BackoffTime > stopwatch.Elapsed ? shouldRetry.BackoffTime - stopwatch.Elapsed : TimeSpan.Zero; + // if we're going to retry, force an additional async continuation so we don't have a gigantic + // stack built up by all these retries + await Task.Yield(); } - - if (backoffTime != TimeSpan.Zero) + catch { - await Task.Delay(backoffTime, cancellationToken); + // if we're going to completely fail, we want to toss all the async continuation + // stack frames so we don't have a gigantic stack trace (which has serious performance + // implications) + await Task.Yield(); + + throw; } } } diff --git a/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs b/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs index c50d43388b..64ead265bc 100644 --- a/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs +++ b/Microsoft.Azure.Cosmos/src/direct/RntbdConstants.cs @@ -497,6 +497,14 @@ public enum RequestIdentifiers : ushort PopulateCapacityType = 0x00CB, TraceParent = 0x00CC, TraceState = 0x00CD, + GlobalDatabaseAccountName = 0x00CE, + EnableConflictResolutionPolicyUpdate = 0x00CF, + ClientIpAddress = 0x00D0, + IsRequestNotAuthorized = 0x00D1, + StartEpkHash = 0x00D2, + EndEpkHash = 0x00D3, + AllowDocumentReadsInOfflineRegion = 0x00D4, + PopulateCurrentPartitionThroughputInfo = 0x00D5, } public sealed class Request : RntbdTokenStream @@ -692,6 +700,14 @@ public sealed class Request : RntbdTokenStream public RntbdToken populateCapacityType; public RntbdToken traceParent; public RntbdToken traceState; + public RntbdToken globalDatabaseAccountName; + public RntbdToken enableConflictResolutionPolicyUpdate; + public RntbdToken clientIpAddress; + public RntbdToken isRequestNotAuthorized; + public RntbdToken startEpkHash; + public RntbdToken endEpkHash; + public RntbdToken allowDocumentReadsInOfflineRegion; + public RntbdToken populateCurrentPartitionThroughputInfo; public Request() { @@ -884,6 +900,14 @@ public Request() this.populateCapacityType = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCapacityType); this.traceParent = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceParent); this.traceState = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.TraceState); + this.globalDatabaseAccountName = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.GlobalDatabaseAccountName); + this.enableConflictResolutionPolicyUpdate = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.EnableConflictResolutionPolicyUpdate); + this.clientIpAddress = new RntbdToken(false, RntbdTokenTypes.String, (ushort)RequestIdentifiers.ClientIpAddress); + this.isRequestNotAuthorized = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.IsRequestNotAuthorized); + this.startEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.StartEpkHash); + this.endEpkHash = new RntbdToken(false, RntbdTokenTypes.Bytes, (ushort)RequestIdentifiers.EndEpkHash); + this.allowDocumentReadsInOfflineRegion = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.AllowDocumentReadsInOfflineRegion); + this.populateCurrentPartitionThroughputInfo = new RntbdToken(false, RntbdTokenTypes.Byte, (ushort)RequestIdentifiers.PopulateCurrentPartitionThroughputInfo); this.tokens = new RntbdToken[] { @@ -1093,6 +1117,14 @@ public Request() this.populateCapacityType, this.traceParent, this.traceState, + this.globalDatabaseAccountName, + this.enableConflictResolutionPolicyUpdate, + this.clientIpAddress, + this.isRequestNotAuthorized, + this.startEpkHash, + this.endEpkHash, + this.allowDocumentReadsInOfflineRegion, + this.populateCurrentPartitionThroughputInfo, }; } } @@ -1183,6 +1215,7 @@ public enum ResponseIdentifiers : ushort MinGLSNForDocumentOperations = 0x0068, MinGLSNForTombstoneOperations = 0x0069, HighestTentativeWriteLLSN = 0x0070, + PartitionThroughputInfo = 0x0071, } // diff --git a/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs b/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs index a1ce19d574..1d82ec0bbd 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ServiceIdentity.cs @@ -3,6 +3,7 @@ //------------------------------------------------------------ namespace Microsoft.Azure.Documents { + using Newtonsoft.Json; using System; internal interface IServiceIdentity @@ -19,6 +20,7 @@ internal sealed class ServiceIdentity : IServiceIdentity /// /// Needed for TestForWhiteListedPersistedTypes to succeed /// + [JsonConstructor] private ServiceIdentity() { } @@ -30,18 +32,21 @@ public ServiceIdentity(string federationId, Uri serviceName, bool isMasterServic this.IsMasterService = isMasterService; } + [JsonProperty] public string FederationId { get; private set; } + [JsonProperty] public Uri ServiceName { get; private set; } + [JsonProperty] public bool IsMasterService { get; diff --git a/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs b/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs index ba5b7001a3..bfa014b899 100644 --- a/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs +++ b/Microsoft.Azure.Cosmos/src/direct/Snapshot.cs @@ -39,9 +39,7 @@ namespace Microsoft.Azure.Documents #endif class Snapshot : Resource { -#pragma warning disable CS0108 // Member hides inherited member; missing new keyword - private static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); -#pragma warning restore CS0108 // Member hides inherited member; missing new keyword + private new static DateTime UnixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); private SnapshotContent snapshotContent; diff --git a/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs b/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs index e019a29ba8..dc74d8ba14 100644 --- a/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs +++ b/Microsoft.Azure.Cosmos/src/direct/SnapshotContent.cs @@ -25,6 +25,7 @@ internal sealed class SnapshotContent : JsonSerializable private IList partitionKeyRangeResourceIds; private IList dataDirectories; + private IList storageAccountUris; // If Snapshot contains ClientEncryptionKeys this will be set private IList serializedClientEncryptionKeys; @@ -386,6 +387,28 @@ internal set } } + /// + /// Gets the list of StorageAccountUris. + /// + [JsonProperty(PropertyName = Constants.SnapshotProperties.StorageAccountUris)] + public IList StorageAccountUris + { + get + { + if (this.storageAccountUris == null) + { + this.storageAccountUris = base.GetValue>(Constants.SnapshotProperties.StorageAccountUris); + } + + return this.storageAccountUris; + } + internal set + { + this.storageAccountUris = value; + base.SetValue(Constants.SnapshotProperties.StorageAccountUris, value); + } + } + [JsonIgnore] public IList ClientEncryptionKeysList { diff --git a/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs b/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs index 1c519662ff..6248082c74 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StatusCodes.cs @@ -8,6 +8,8 @@ namespace Microsoft.Azure.Documents { internal enum StatusCodes { + Processing = 102, + // Success Ok = 200, Created = 201, @@ -77,6 +79,7 @@ internal enum SubStatusCodes PartitionMigrationSourcePartitionDeletedInMaster = 1034, PartitionMigrationSharedThroughputDatabasePartitionResourceNotFoundInMaster = 1035, PartitionMigrationPartitionResourceNotFoundInMaster = 1036, + PartitionMigrationFailedToUpdateDNS = 1037, // 403: Forbidden Substatus. WriteForbidden = 3, @@ -106,9 +109,18 @@ internal enum SubStatusCodes InsufficientBindablePartitions = 1007, ComputeFederationNotFound = 1012, OperationPaused = 9001, - ServiceIsOffline = 9002, InsufficientCapacity = 9003, + // Federation Buildout / Expansion error codes + AggregatedHealthStateError = 6001, // - Aggregated health state is Error + ApplicationHealthStateError = 6002, // - Any application is in Warning or Error state + HealthStateError = 6003, // - Any health events in Error state are found + UnhealthyEventFound = 6004, // - Any unhealthy evaluations are found (except for Warning evaluations on Nodes) + ClusterHealthEmpty = 6005, // Cluster Health States is empty + AllocationFailed = 6006, // Allocation failed for federation + OperationResultNull = 6007, // Null operation result + OperationResultUnexpected = 6008, // Null operation result + //412: PreCondition Failed SplitIsDisabled = 2001, CollectionsInPartitionGotUpdated = 2002, @@ -139,17 +151,29 @@ internal enum SubStatusCodes PartitionMigrationSourceAndTargetFederationSubregionIsNotSame = 2024, PartitionMigrationFailedToCreatePartitionMigrationLocks = 2025, PartitionMigrationFailedToResolvePartitionInformation = 2026, - PartitionMigrationTopologyHasWriteRegionEmpty = 2027, PartitionMigrationIsDisableOnTheGlobalDatabaseAccount = 2028, PartitionMigrationIsDisableOnTheRunnerAccount = 2029, PartitionMigrationCanNotProceedForInactiveRegionalDatabaseAccount = 2030, PartitionMigrationDidNotCompleteWaitForFullSyncInTenRetries = 2031, + PartitionMigrationCanNotProceedForDeletingRegionalDatabaseAccount = 2032, + PartitionMigrationCanNotProceedForDeletionFailedRegionalDatabaseAccount = 2033, + PartitionMigrationCanNotAcquireRegionalDatabaseAccountPartitionMigrationLock = 2034, + PartitionMigrationIsDisabledOnReadyForDecommissionFederation = 2035, + PartitionMigrationCanNotAcquirePartitionLock = 2036, + PartitionMigrationCanNotAcquirePartitionKeyRangesLock = 2037, + PartitionMigrationCanNotProceedForDeletingGlobalDatabaseAccount = 2038, + PartitionMigrationCanNotProceedForDeletionFailedGlobalDatabaseAccount = 2039, + PartitionMigrationCanNotProceedForRevokedGlobalDatabaseAccount = 2040, + PartitionMigrationMasterServiceTopologyHasWriteRegionEmpty = 2041, + PartitionMigrationWriteRegionServiceTopologyHasWriteRegionEmpty = 2042, + PartitionMigrationIsDisabledOnFinalizingDecommissionFederation = 2043, // 500: InternalServerError ConfigurationNameNotEmpty = 3001, ConfigurationOperationCancelled = 3002, InvalidAccountConfiguration = 3003, FederationDoesnotExistOrIsLocked = 3004, + PartitionFailoverErrorCode = 3010, // 429: Request Rate Too Large PrepareTimeLimitExceeded = 3207, @@ -177,6 +201,7 @@ internal enum SubStatusCodes InvalidKeyVaultSecretURI = 4014, // Indicates the Key Vault secret URI is invalid. UndefinedDefaultIdentity = 4015, // Indicates that the account has an undefined default identity. NspOutboundDenied = 4016, // Indicates that the account's NSP is blocking outbound requests to Key Vault. + KeyVaultNotFound = 4017, // Indicates that the Key Vault could not be found by the system. // Keep in sync with Microsoft.Azure.Cosmos.ServiceFramework.Security.AadAuthentication.AadSubStatusCodes // 401 : Unauthorized Exception (User-side errors start with 50) @@ -227,7 +252,11 @@ internal enum SubStatusCodes // 401 Unauthorized Exception (mutual TLS client auth failed) MutualTlsClientAuthFailed = 5600, + // 200 OK.GW response to GET DocService request. + LocationsModified = 5700, // Indicates locations derived from topology have been modified due to region being offlined. + // SDK Codes (Client) + // IMPORTANT - keep these consistent with Java SDK as well TransportGenerated410 = 20001, TimeoutGenerated410 = 20002, TransportGenerated503 = 20003, @@ -235,8 +264,10 @@ internal enum SubStatusCodes Client_ThreadStarvation = 20005, Channel_Closed = 20006, MalformedContinuationToken = 20007, + // EndToEndOperationCancelled = 20008 - cancellation by e2e retry policy - currently only applicable in Java //SDK Codes (Server) + // IMPORTANT - keep these consistent with Java SDK as well Server_NameCacheIsStaleExceededRetryLimit = 21001, Server_PartitionKeyRangeGoneExceededRetryLimit = 21002, Server_CompletingSplitExceededRetryLimit = 21003, @@ -245,7 +276,12 @@ internal enum SubStatusCodes Server_GlobalStrongWriteBarrierNotMet = 21006, Server_ReadQuorumNotMet = 21007, ServerGenerated503 = 21008, - Server_NoValidStoreResponse = 21009 + Server_NoValidStoreResponse = 21009, + // ServerGenerated408 = 21010 - currently only applicable in Java + + // Data Transfer Application related + MissingPartitionKeyInDataTransfer = 22001, + InvalidPartitionKeyInDataTransfer = 22002 } internal static class StatusCodesExtensions diff --git a/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs b/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs index 9b2b968c93..e6fefde124 100644 --- a/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs +++ b/Microsoft.Azure.Cosmos/src/direct/StoreResponseNameValueCollection.cs @@ -91,6 +91,7 @@ internal class StoreResponseNameValueCollection : INameValueCollection, IEnumera public string OwnerFullName { get; set; } public string OwnerId { get; set; } public string PartitionKeyRangeId { get; set; } + public string PartitionThroughputInfo { get; set; } public string PendingPKDelete { get; set; } public string PhysicalPartitionId { get; set; } public string QueryExecutionInfo { get; set; } @@ -215,6 +216,7 @@ public void Clear() this.OwnerFullName = null; this.OwnerId = null; this.PartitionKeyRangeId = null; + this.PartitionThroughputInfo = null; this.PendingPKDelete = null; this.PhysicalPartitionId = null; this.QueryExecutionInfo = null; @@ -311,6 +313,7 @@ public INameValueCollection Clone() OwnerFullName = this.OwnerFullName, OwnerId = this.OwnerId, PartitionKeyRangeId = this.PartitionKeyRangeId, + PartitionThroughputInfo = this.PartitionThroughputInfo, PendingPKDelete = this.PendingPKDelete, PhysicalPartitionId = this.PhysicalPartitionId, QueryExecutionInfo = this.QueryExecutionInfo, @@ -691,6 +694,10 @@ IEnumerator> IEnumerable(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); } + if (this.PartitionThroughputInfo != null) + { + yield return new KeyValuePair(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); + } if (this.lazyNotCommonHeaders != null) { @@ -1046,6 +1053,10 @@ public IEnumerable Keys() { yield return WFConstants.BackendHeaders.HighestTentativeWriteLLSN; } + if (this.PartitionThroughputInfo != null) + { + yield return WFConstants.BackendHeaders.PartitionThroughputInfo; + } if (this.lazyNotCommonHeaders != null) { @@ -1400,6 +1411,10 @@ public NameValueCollection ToNameValueCollection() { this.nameValueCollection.Add(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, this.HighestTentativeWriteLLSN); } + if (this.PartitionThroughputInfo != null) + { + this.nameValueCollection.Add(WFConstants.BackendHeaders.PartitionThroughputInfo, this.PartitionThroughputInfo); + } if(this.lazyNotCommonHeaders != null) { foreach (KeyValuePair keyValuePair in this.lazyNotCommonHeaders) @@ -2055,6 +2070,10 @@ public string Get(string key) { return this.MergeProgressBlocked; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) + { + return this.PartitionThroughputInfo; + } if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) { return this.IsRUPerMinuteUsed; @@ -2070,6 +2089,11 @@ public string Get(string key) return this.MergeProgressBlocked; } + if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + return this.PartitionThroughputInfo; + } + break; case 38: if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) @@ -2110,6 +2134,10 @@ public string Get(string key) break; case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) + { + return this.SoftMaxAllowedThroughput; + } if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) { return this.HighestTentativeWriteLLSN; @@ -3550,6 +3578,16 @@ public void UpdateHelper( this.MergeProgressBlocked = value; return; } + if (object.ReferenceEquals(WFConstants.BackendHeaders.PartitionThroughputInfo, key)) + { + if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionThroughputInfo = value; + return; + } if (string.Equals(WFConstants.BackendHeaders.IsRUPerMinuteUsed, key, StringComparison.OrdinalIgnoreCase)) { if (throwIfAlreadyExists && this.IsRUPerMinuteUsed != null) @@ -3580,6 +3618,16 @@ public void UpdateHelper( this.MergeProgressBlocked = value; return; } + if (string.Equals(WFConstants.BackendHeaders.PartitionThroughputInfo, key, StringComparison.OrdinalIgnoreCase)) + { + if (throwIfAlreadyExists && this.PartitionThroughputInfo != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.PartitionThroughputInfo = value; + return; + } break; case 38: if (object.ReferenceEquals(WFConstants.BackendHeaders.VectorClockLocalProgress, key)) @@ -3664,6 +3712,16 @@ public void UpdateHelper( } break; case 40: + if (object.ReferenceEquals(WFConstants.BackendHeaders.SoftMaxAllowedThroughput, key)) + { + if (throwIfAlreadyExists && this.SoftMaxAllowedThroughput != null) + { + throw new ArgumentException($"The {key} already exists in the collection"); + } + + this.SoftMaxAllowedThroughput = value; + return; + } if (object.ReferenceEquals(WFConstants.BackendHeaders.HighestTentativeWriteLLSN, key)) { if (throwIfAlreadyExists && this.HighestTentativeWriteLLSN != null) diff --git a/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs b/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs index 8d9304997a..3c8d6166a5 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TimerPool.cs @@ -199,6 +199,7 @@ public PooledTimer GetPooledTimer(int timeoutInSeconds) /// /// get a timer with timeout specified as a TimeSpan /// + /// /// public PooledTimer GetPooledTimer(TimeSpan timeout) { diff --git a/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs b/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs index 8b68361ed3..0ddfdc2f3c 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TransportSerialization.cs @@ -108,9 +108,15 @@ internal static SerializedRequest BuildRequestForProxy( ResourceOperation resourceOperation, Guid activityId, BufferProvider bufferProvider, + string globalDatabaseAccountName, out int headerSize, out int? bodySize) { + if (string.IsNullOrEmpty(globalDatabaseAccountName)) + { + throw new ArgumentNullException(nameof(globalDatabaseAccountName)); + } + RntbdConstants.Request rntbdRequest = new(); // for proxy, transportRequestId and replicapath are optional. @@ -127,6 +133,13 @@ internal static SerializedRequest BuildRequestForProxy( rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[0]; rntbdRequest.tokens[0] = rntbdRequest.effectivePartitionKey; + // Account name is the second token + tokenIndex = Array.IndexOf(rntbdRequest.tokens, rntbdRequest.globalDatabaseAccountName); + rntbdRequest.tokens[tokenIndex] = rntbdRequest.tokens[1]; + rntbdRequest.tokens[1] = rntbdRequest.globalDatabaseAccountName; + rntbdRequest.globalDatabaseAccountName.value.valueBytes = BytesSerializer.GetBytesForString(globalDatabaseAccountName, rntbdRequest); + rntbdRequest.globalDatabaseAccountName.isPresent = true; + return BuildRequestCore( request, ref rntbdRequest, @@ -272,6 +285,8 @@ private static SerializedRequest BuildRequestCore( TransportSerialization.AddIsMaterializedViewSourceSchemaReplaceBatchRequest(requestHeaders, rntbdRequest); TransportSerialization.AddIsCassandraAlterTypeRequest(request, rntbdRequest); TransportSerialization.AddHighPriorityForcedBackup(requestHeaders, rntbdRequest); + TransportSerialization.AddEnableConflictResolutionPolicyUpdate(requestHeaders, rntbdRequest); + TransportSerialization.AddAllowDocumentReadsInOfflineRegion(requestHeaders, rntbdRequest); TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.Authorization, requestHeaders.Authorization, rntbdRequest.authorizationToken, rntbdRequest); TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.SessionToken, requestHeaders.SessionToken, rntbdRequest.sessionToken, rntbdRequest); @@ -355,6 +370,11 @@ private static SerializedRequest BuildRequestCore( TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCapacityType, requestHeaders.PopulateCapacityType, rntbdRequest.populateCapacityType, rntbdRequest); TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceParent, requestHeaders.TraceParent, rntbdRequest.traceParent, rntbdRequest); TransportSerialization.FillTokenFromHeader(request, HttpConstants.HttpHeaders.TraceState, requestHeaders.TraceState, rntbdRequest.traceState, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.ClientIpAddress, requestHeaders.ClientIpAddress, rntbdRequest.clientIpAddress, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.IsRequestNotAuthorized, requestHeaders.IsRequestNotAuthorized, rntbdRequest.isRequestNotAuthorized, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.StartEpkHash, headerStringValue: null, rntbdRequest.startEpkHash, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.EndEpkHash, headerStringValue: null, rntbdRequest.endEpkHash, rntbdRequest); + TransportSerialization.FillTokenFromHeader(request, WFConstants.BackendHeaders.PopulateCurrentPartitionThroughputInfo, requestHeaders.PopulateCurrentPartitionThroughputInfo, rntbdRequest.populateCurrentPartitionThroughputInfo, rntbdRequest); // will be null in case of direct, which is fine - BE will use the value from the connection context message. // When this is used in Gateway, the header value will be populated with the proxied HTTP request's header, and @@ -547,8 +567,10 @@ private static RntbdConstants.RntbdOperationType GetRntbdOperationType(Operation return RntbdConstants.RntbdOperationType.Batch; case OperationType.CompleteUserTransaction: return RntbdConstants.RntbdOperationType.CompleteUserTransaction; + case OperationType.MetadataCheckAccess: + return RntbdConstants.RntbdOperationType.MetadataCheckAccess; #if !COSMOSCLIENT - case OperationType.Crash: + case OperationType.Crash: return RntbdConstants.RntbdOperationType.Crash; case OperationType.Pause: return RntbdConstants.RntbdOperationType.Pause; @@ -606,8 +628,6 @@ private static RntbdConstants.RntbdOperationType GetRntbdOperationType(Operation return RntbdConstants.RntbdOperationType.ForcePartitionBackup; case OperationType.MasterInitiatedProgressCoordination: return RntbdConstants.RntbdOperationType.MasterInitiatedProgressCoordination; - case OperationType.MetadataCheckAccess: - return RntbdConstants.RntbdOperationType.MetadataCheckAccess; case OperationType.CreateSystemSnapshot: return RntbdConstants.RntbdOperationType.CreateSystemSnapshot; case OperationType.CreateRidRangeResources: @@ -2585,6 +2605,18 @@ private static void AddHighPriorityForcedBackup(RequestNameValueCollection reque } } + private static void AddEnableConflictResolutionPolicyUpdate(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.EnableConflictResolutionPolicyUpdate)) + { + rntbdRequest.enableConflictResolutionPolicyUpdate.value.valueByte = (requestHeaders.EnableConflictResolutionPolicyUpdate. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.enableConflictResolutionPolicyUpdate.isPresent = true; + } + } + private static void AddPriorityLevelHeader(DocumentServiceRequest request, string headerName, string headerStringValue, RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) { PriorityLevel priorityLevel = PriorityLevel.High; @@ -2632,5 +2664,17 @@ private static void AddPriorityLevelHeader(DocumentServiceRequest request, strin rntbdRequest.priorityLevel.value.valueByte = (byte) rntbdPriorityLevel; rntbdRequest.priorityLevel.isPresent = true; } + + private static void AddAllowDocumentReadsInOfflineRegion(RequestNameValueCollection requestHeaders, RntbdConstants.Request rntbdRequest) + { + if (!string.IsNullOrEmpty(requestHeaders.AllowDocumentReadsInOfflineRegion)) + { + rntbdRequest.allowDocumentReadsInOfflineRegion.value.valueByte = (requestHeaders.AllowDocumentReadsInOfflineRegion. + Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase)) + ? (byte)0x01 + : (byte)0x00; + rntbdRequest.allowDocumentReadsInOfflineRegion.isPresent = true; + } + } } } \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs b/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs index efdd9e3c45..d9d183730a 100644 --- a/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs +++ b/Microsoft.Azure.Cosmos/src/direct/TriggerOperation.cs @@ -36,6 +36,11 @@ enum TriggerOperation : short /// /// Specifies replace operations only. /// - Replace = 0x4 + Replace = 0x4, + + /// + /// Specifies upsert operations only. + /// + Upsert = 0x5 } } diff --git a/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs b/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs index 962f01779b..852456c5e3 100644 --- a/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs +++ b/Microsoft.Azure.Cosmos/src/direct/ValueStopwatch.cs @@ -27,9 +27,7 @@ internal struct ValueStopwatch /// public static readonly bool IsHighResolution = Stopwatch.IsHighResolution; -#pragma warning disable CS1570 // XML comment has badly formed XML -#pragma warning disable CS1570 // XML comment has badly formed XML -/// + /// /// We pack everything into a single long, so using this doesn't inflate any objects with it as a field. /// /// State is interpreted as follows @@ -47,8 +45,6 @@ internal struct ValueStopwatch /// to account for any existing duration. /// private long state; -#pragma warning restore CS1570 // XML comment has badly formed XML -#pragma warning restore CS1570 // XML comment has badly formed XML /// public readonly bool IsRunning diff --git a/Microsoft.Azure.Cosmos/src/direct/WFConstants.cs b/Microsoft.Azure.Cosmos/src/direct/WFConstants.cs index f50dbf45a02944e5681325cf25b4878454af07f8..918c6cad9b81641ebdc0952c77abeb8636e47746 100644 GIT binary patch delta 470 zcmdmUm~qEB#tjx4`pyjb40#M`3^@#$49N^73_%R348=gP9EMULFB2>q0Oo__D<_{; zvA0bH>PTcr0;)-6&;^R3noxwrgaRZJ3{}H7>u4lcaF;R^0U^k+lF5kz!jmVdim-cv z9g{zKVS*`&{6iD*$wyR0ChN%tO;%77LQ%_Tr9AnWi4a`g!AW3pS3=F?1Un;Pkhj1# zFnBT)FgP-#Fr-YrsH-WN4E8WYMi;220O*lKuiY|5z&g}@*H1x5*jAJF+F zK;57q$pEs8fI6xeQYSxjQJ#Fyjcf7?FCNJ}uo{pl=&Ck~c~4#^$i`U&)a?qiDSI-b zjr3##TRusU*@-~YN`SVff@FYn22iAUa$&GHw<|C#Qc!h>f?S+}MYZ%~w#01!KP`6i delta 22 ecmdmSj&aXn#tjx4o82@+EGB0qS50n8+Xet}`w7ti diff --git a/Microsoft.Azure.Cosmos/src/direct/WindowsSystemUtilizationReader.cs b/Microsoft.Azure.Cosmos/src/direct/WindowsSystemUtilizationReader.cs index 6baffbcaa0..35c64dd1cf 100644 --- a/Microsoft.Azure.Cosmos/src/direct/WindowsSystemUtilizationReader.cs +++ b/Microsoft.Azure.Cosmos/src/direct/WindowsSystemUtilizationReader.cs @@ -85,6 +85,8 @@ private static class NativeMethods /// /// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex /// + /// + /// /// /// [DllImport("kernel32.dll", SetLastError = true)] diff --git a/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs b/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs index e6c61819f8..87ec56777d 100644 --- a/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs +++ b/Microsoft.Azure.Cosmos/src/direct/rntbd2/TransportClient.cs @@ -148,10 +148,6 @@ internal override async Task InvokeStoreAsync( resourceOperation, activityId, transportRequestStats); transportRequestStats.RecordState(TransportRequestStats.RequestStage.Completed); storeResponse.TransportRequestStats = transportRequestStats; - -#if NETSTANDARD2_0_OR_GREATER - recorder?.Record(physicalAddress.Uri, storeResponse: storeResponse); -#endif } catch (TransportException ex) { @@ -275,13 +271,15 @@ internal override async Task InvokeStoreAsync( recorder?.Record(physicalAddress.Uri, documentClientException: exception); throw; } + + // Record the information of the sucessfull response in the end, it also make sure it is not getting called twice. + recorder?.Record(physicalAddress.Uri, storeResponse: storeResponse); #else catch (DocumentClientException) { throw; } #endif - return storeResponse; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs index 50b0125338..9a5c4255a7 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientConfigurationDiagnosticTest.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; + using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -45,7 +46,11 @@ public async Task ClientConfigTest() ItemResponse response = await this.Container.CreateItemAsync(testItem, new Cosmos.PartitionKey(testItem.pk)); Assert.IsNotNull(response.Diagnostics); ITrace trace = ((CosmosTraceDiagnostics)response.Diagnostics).Value; - Assert.AreEqual(trace.Data.Count, 1); +#if PREVIEW + Assert.AreEqual(trace.Data.Count, 2, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); // Distributed Tracing Id +#else + Assert.AreEqual(trace.Data.Count, 1, string.Join(",", trace.Data.Select(a => $"{a.Key}: {a.Value}"))); +#endif ClientConfigurationTraceDatum clientConfigurationTraceDatum = (ClientConfigurationTraceDatum)trace.Data["Client Configuration"]; Assert.IsNotNull(clientConfigurationTraceDatum.UserAgentContainer.UserAgent); } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs index 8bbb7f5d54..1813700e05 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientCreateAndInitializeTest.cs @@ -138,7 +138,7 @@ public async Task DatabaseIncorrectTest() catch (CosmosException ex) { Assert.IsTrue(ex.StatusCode == HttpStatusCode.NotFound); - throw ex; + throw; } } @@ -156,7 +156,7 @@ public async Task ContainerIncorrectTest() catch (CosmosException ex) { Assert.IsTrue(ex.StatusCode == HttpStatusCode.NotFound); - throw ex; + throw; } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs index c8a9a0aff7..9bbbb980e3 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/ClientTests.cs @@ -290,6 +290,24 @@ public async Task ValidateAzureKeyCredentialDirectModeUpdateAsync() } } + [TestMethod] + public async Task ValidateTryGetAccountProperties() + { + using CosmosClient cosmosClient = new CosmosClient( + ConfigurationManager.AppSettings["GatewayEndpoint"], + ConfigurationManager.AppSettings["MasterKey"] + ); + + Assert.IsFalse(cosmosClient.DocumentClient.TryGetCachedAccountProperties(out AccountProperties propertiesFromMethod)); + + AccountProperties accountProperties = await cosmosClient.ReadAccountAsync(); + + Assert.IsTrue(cosmosClient.DocumentClient.TryGetCachedAccountProperties(out propertiesFromMethod)); + + Assert.AreEqual(accountProperties.Consistency.DefaultConsistencyLevel, propertiesFromMethod.Consistency.DefaultConsistencyLevel); + Assert.AreEqual(accountProperties.Id, propertiesFromMethod.Id); + } + private int TaskStartedCount = 0; private async Task ReadNotFound(Container container) diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs index 5615f1dc34..4bb3eb27b6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/CosmosContainerTests.cs @@ -18,6 +18,7 @@ namespace Microsoft.Azure.Cosmos.SDK.EmulatorTests using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; + using ClientEncryptionIncludedPath = Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath; [TestClass] public class CosmosContainerTests @@ -1384,7 +1385,7 @@ public async Task ClientEncryptionPolicyTest() EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", EncryptionType = "Deterministic" }, - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = "/path2", ClientEncryptionKeyId = "dekId2", @@ -1397,7 +1398,7 @@ public async Task ClientEncryptionPolicyTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(includedPaths:paths,policyFormatVersion:2) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(includedPaths:paths,policyFormatVersion:2) }; ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(setting); @@ -1406,7 +1407,7 @@ public async Task ClientEncryptionPolicyTest() ContainerProperties responseSettings = containerResponse; Assert.AreEqual(3, responseSettings.ClientEncryptionPolicy.IncludedPaths.Count()); - ClientEncryptionIncludedPath includedPath = responseSettings.ClientEncryptionPolicy.IncludedPaths.ElementAt(0); + Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath includedPath = responseSettings.ClientEncryptionPolicy.IncludedPaths.ElementAt(0); Assert.AreEqual(partitionKeyPath, includedPath.Path); Assert.AreEqual("dekId1", includedPath.ClientEncryptionKeyId); Assert.AreEqual("AEAD_AES_256_CBC_HMAC_SHA256", includedPath.EncryptionAlgorithm); @@ -1431,16 +1432,16 @@ public async Task ClientEncryptionPolicyTest() // version 1 test. containerName = Guid.NewGuid().ToString(); partitionKeyPath = "/users"; - paths = new Collection() + paths = new Collection() { - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = "/path1", ClientEncryptionKeyId = "dekId1", EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", EncryptionType = "Randomized" }, - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = "/path2", ClientEncryptionKeyId = "dekId2", @@ -1453,7 +1454,7 @@ public async Task ClientEncryptionPolicyTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(paths) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(paths) }; containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(setting); @@ -1585,7 +1586,7 @@ public async Task ClientEncryptionPolicyFailureTest() EncryptionAlgorithm = "AEAD_AES_256_CBC_HMAC_SHA256", EncryptionType = "Randomized" }, - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = "/path1", ClientEncryptionKeyId = "dekId1", @@ -1598,7 +1599,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) }; await this.cosmosDatabase.CreateContainerAsync(setting); @@ -1633,7 +1634,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) }; await this.cosmosDatabase.CreateContainerAsync(setting); @@ -1647,9 +1648,9 @@ public async Task ClientEncryptionPolicyFailureTest() // failure due to policy format version 1. for Pk and Id try { - Collection pathsToEncryptWithPartitionKey = new Collection() + Collection pathsToEncryptWithPartitionKey = new Collection() { - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = partitionKeyPath, ClientEncryptionKeyId = "dekId1", @@ -1662,7 +1663,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(pathsToEncryptWithPartitionKey) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(pathsToEncryptWithPartitionKey) }; await this.cosmosDatabase.CreateContainerAsync(setting); @@ -1675,9 +1676,9 @@ public async Task ClientEncryptionPolicyFailureTest() try { - Collection pathsToEncryptWithPartitionKey = new Collection() + Collection pathsToEncryptWithPartitionKey = new Collection() { - new ClientEncryptionIncludedPath() + new Microsoft.Azure.Cosmos.ClientEncryptionIncludedPath() { Path = "/id", ClientEncryptionKeyId = "dekId1", @@ -1690,7 +1691,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKey = new Documents.PartitionKeyDefinition() { Paths = new Collection { partitionKeyPath }, Kind = Documents.PartitionKind.Hash }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(pathsToEncryptWithPartitionKey) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(pathsToEncryptWithPartitionKey) }; await this.cosmosDatabase.CreateContainerAsync(setting); @@ -1719,7 +1720,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKeyPaths = new Collection { "/path1", "/id" }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) }; await this.cosmosDatabase.CreateContainerAsync(setting); @@ -1748,7 +1749,7 @@ public async Task ClientEncryptionPolicyFailureTest() { Id = containerName, PartitionKeyPaths = new Collection { partitionKeyPath, "/path1" }, - ClientEncryptionPolicy = new ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) + ClientEncryptionPolicy = new Microsoft.Azure.Cosmos.ClientEncryptionPolicy(includedPaths: pathsToEncryptWithPartitionKey, policyFormatVersion: 2) }; await this.cosmosDatabase.CreateContainerAsync(setting); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs index 7ffc36bdbd..5ea03bf0b6 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Linq/LinqAttributeContractBaselineTests.cs @@ -9,14 +9,13 @@ namespace Microsoft.Azure.Cosmos.Services.Management.Tests.LinqProviderTests using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; - using Newtonsoft.Json; - using Newtonsoft.Json.Linq; - using VisualStudio.TestTools.UnitTesting; + using System.Threading.Tasks; using BaselineTest; using Microsoft.Azure.Cosmos.Linq; using Microsoft.Azure.Cosmos.SDK.EmulatorTests; using Microsoft.Azure.Documents; - using System.Threading.Tasks; + using Newtonsoft.Json; + using VisualStudio.TestTools.UnitTesting; /// /// Class that tests to see that we honor the attributes for members in a class / struct when we create LINQ queries. @@ -173,10 +172,11 @@ public Datum2(string jsonProperty, string dataMember, string defaultMember, stri [TestMethod] public void TestAttributePriority() { - Assert.AreEqual("jsonProperty", TypeSystem.GetMemberName(typeof(Datum).GetMember("JsonProperty").First())); - Assert.AreEqual("dataMember", TypeSystem.GetMemberName(typeof(Datum).GetMember("DataMember").First())); - Assert.AreEqual("Default", TypeSystem.GetMemberName(typeof(Datum).GetMember("Default").First())); - Assert.AreEqual("jsonPropertyHasHigherPriority", TypeSystem.GetMemberName(typeof(Datum).GetMember("JsonPropertyAndDataMember").First())); + ICosmosLinqSerializer cosmosLinqSerializer = new DefaultCosmosLinqSerializer(); + Assert.AreEqual("jsonProperty", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("JsonProperty").First())); + Assert.AreEqual("dataMember", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("DataMember").First())); + Assert.AreEqual("Default", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("Default").First())); + Assert.AreEqual("jsonPropertyHasHigherPriority", cosmosLinqSerializer.SerializeMemberName(typeof(Datum).GetMember("JsonPropertyAndDataMember").First())); } /// diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj index 7ff30b3cee..ada11a75c0 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Microsoft.Azure.Cosmos.EmulatorTests.csproj @@ -19,7 +19,6 @@ - diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs new file mode 100644 index 0000000000..0edd95b22d --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/ConflictsE2ETest.cs @@ -0,0 +1,313 @@ +namespace Microsoft.Azure.Cosmos.EmulatorTests.Query +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Net; + using System.Threading; + using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.CosmosElements; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + /// + /// This is an end to end test that requires connecting to azure cosmos db accounts. + /// + [TestClass] + public class ConflictsE2ETest + { + private const int MaxRetries = 10; + + private const string Database = "Microsoft.Azure.Cosmos.EmulatorTests.Conflicts"; + private const string Collection = "ConflictsTest"; + private const string Key = ""; + private static readonly Endpoint Endpoint1 = new Endpoint("", ConnectionMode.Direct); + private static readonly Endpoint Endpoint2 = new Endpoint("", ConnectionMode.Direct); + + private class Endpoint + { + public Endpoint(string url, ConnectionMode connectionMode) + { + this.Url = url; + this.ConnectionMode = connectionMode; + } + + public ConnectionMode ConnectionMode { get; } + + public string Url { get; } + } + + /// + /// Tests querying conflicts in a cosmosdb collection. + /// + /// + /// This test uses ConflictsTestSettings.json for test configuration. + /// 1. An actual cosmosdb account in Azure is required for this test to run since none of the emulators do not allow for required test setup. + /// 2. Test setup will create a well known database (drop if it exists) and collection. + /// 3. The conditions for generating a conflict are subject to backend non-determinism. For increasing chances of generating a conflict: + /// - Ensure that the account is set to use eventual consistency + /// - Use more than 2 regions in the configuration. + /// + /// + [Ignore] + [TestMethod] + public async Task TestConflicts() + { + Assert.IsTrue(!string.IsNullOrWhiteSpace(Key), "Please specify a valid key"); + + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers = await this.CreateDatabaseAndContainer( + Database, + Collection, + Key, + Endpoint1, + Endpoint2); + + await this.InsertWithoutConflict(cosmosContainers); + await this.InsertWithConflict(cosmosContainers); + await this.VerifyConflict(cosmosContainers); + } + + private async Task VerifyConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + { + List> conflictsUsingDefaultIterator = await this.GetConflictsUsingDefaultIterator(cosmosContainers); + List> conflictsUsingQueryWithoutOptions = await this.GetConflictsUsingQueryWithoutOptions(cosmosContainers); + + Assert.AreEqual(conflictsUsingDefaultIterator.Count, conflictsUsingQueryWithoutOptions.Count, "Conflict count should be identical"); + for (int i = 0; i < conflictsUsingDefaultIterator.Count; i++) + { + Assert.AreEqual(string.Join(",", conflictsUsingDefaultIterator[i].ToString()), string.Join(",", conflictsUsingQueryWithoutOptions[i].ToString())); + } + } + + private async Task>> GetConflictsUsingQueryWithoutOptions(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.GetConflicts( + cosmosContainers, + query: @"SELECT * FROM c", + options: null); + + private async Task>> GetConflictsUsingDefaultIterator(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.GetConflicts(cosmosContainers, query: null, options: null); + + private async Task>> GetConflicts( + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers, + string query, + QueryRequestOptions options) + { + List> allConflicts = new List>(); + foreach ((CosmosClient client, Container container) pair in cosmosContainers) + { + List clientReportedConflicts = new List(); + FeedIterator iterator = pair.container.Conflicts.GetConflictQueryIterator(queryText: query, requestOptions: options); + while (iterator.HasMoreResults) + { + FeedResponse page = await iterator.ReadNextAsync(); + clientReportedConflicts.AddRange(page); + } + + allConflicts.Add(clientReportedConflicts); + } + + // Ideally each client will observe exactly 1 conflict. However this is dependent upon regional (eventual) consistency and underlying race condition with this test. + Assert.IsTrue(allConflicts.Any(list => list.Count == 1), "Exactly 1 conflict is expected!"); + + return allConflicts; + } + + /// + /// Inserts a document that is guaranteed to not conflict with any other. + /// + private async Task InsertWithoutConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.InsertFromMultipleClients( + cosmosContainers, + payloadFormat: @"{{""id"" : ""NoConflict_{0}"", ""type"":""noconflict"", ""pk"":""1""}}", + clientFilter: clientIndex => clientIndex == 0); + + /// + /// Insert documents until exactly one conflict is generated. + /// This is a non-deterministic operation (in terms of both duration and outcome) due to backend's behavior. + /// It will terminate the test based on simple heuristic if desired outcome cannot be achieved. + /// + private async Task InsertWithConflict(IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers) + => await this.InsertFromMultipleClients( + cosmosContainers, + payloadFormat: @"{{""id"" : ""Conflict_{0}"", ""type"":""conflict"", ""pk"":""1"", ""index"":{1}}}"); + + /// + /// Inserts items from multiple clients. + /// + /// Containers to insert documents to. + /// Format of the document with placeholders for insertion iteration (one round across all clients) and optional client index. + /// Optional filter that determines whether a client should be used for insertion. + /// + private async Task InsertFromMultipleClients( + IReadOnlyList<(CosmosClient Client, Container Container)> cosmosContainers, + string payloadFormat, + Func clientFilter = null) + { + PartitionKey partitionKey = new PartitionKey("1"); + bool retry = true; + int i = 0; + + // To offset the backend specific non-determinism, we change the order in which we use containers to create the items. + // Other mitigations to explore include having more than 2 regions and ordering those randomly while creating items. + IEnumerable containersInOrder = cosmosContainers.Select(pair => pair.Container); + IEnumerable containersInReverseOrder = cosmosContainers.Reverse().Select(pair => pair.Container); + while (retry) + { + int clientIndex = 0; + List responses = new List(); + IEnumerable containers = + i % 2 == 1 ? + containersInOrder : + containersInReverseOrder; + foreach (Container container in containers) + { + bool useClient = clientFilter == null || clientFilter(clientIndex); + if (useClient) + { + ResponseMessage response = await this.CreateItem( + container, + string.Format(payloadFormat, i, clientIndex), + partitionKey); + responses.Add(response); + } + + clientIndex++; + } + + Assert.IsTrue(responses.Count > 0, "At least one client should attempt document creation!"); + + // Sometimes the conflicts may be detected (and rejected) by the backend with status code = Conflict synchronously with the request. + // We keep retrying until all clients are able to "successfully" create item in the backend which will be later detected as conflict. + retry = responses.Any(response => response.StatusCode != HttpStatusCode.Created); + i++; + + // Even with the measures above, the conflicts may continue to get detected (and rejected) by the backend perpetually in a synchronous manner. + // After 3000 tries (which can take upto 5 minutes for 2 regions), we determine that the test is inconclusive, since the setup failed. + if (i > 3000) + { + string expectedResponses = string.Join(",", Enumerable.Repeat("Created", cosmosContainers.Count)); + string actualResponses = string.Join(",", responses.Select(response => response.StatusCode.ToString())); + Assert.Fail($@"Document insertion failed after 3000 tries. Please rerun the test. Expected responses : ""{expectedResponses}"". Actual responses : ""{actualResponses}""."); + } + } + } + + private async Task CreateItem(Container container, string payload, PartitionKey partitionKey) + { + return await this.ExecuteOperationWithRetry( + MaxRetries, + () => container.CreateItemStreamAsync( + this.ToStream(payload), + partitionKey), + // Since the test also creates the database and document collection, first few read/write operations on the collection can return NotFound. + responseMessage => responseMessage.StatusCode == HttpStatusCode.NotFound); + } + + private Stream ToStream(string stringValue) + { + MemoryStream stream = new(); + StreamWriter writer = new(stream); + writer.Write(stringValue); + writer.Flush(); + stream.Position = 0; + return stream; + } + + /// + /// Instantiates client and container pointing to each region. Creates (drops if exists) database, container using one region's connections. + /// + /// Returns the CosmosClient and Container pointing to each region. + private async Task> CreateDatabaseAndContainer( + string database, + string collection, + string key, + params Endpoint[] endpoints) + { + Assert.IsTrue(endpoints?.Length > 1, "At least one endpoint must be specified"); + + HashSet endpointSet = new HashSet(endpoints.Select(endpoint => endpoint.Url)); + Assert.AreEqual(endpoints.Length, endpointSet.Count, "Please specify unique endpoints!"); + + int endpointIndex = 0; + List<(CosmosClient Client, Container Container)> clients = new(); + foreach (Endpoint endpoint in endpoints) + { + CosmosClient client = new CosmosClient(endpoint.Url, key, new CosmosClientOptions { ConnectionMode = endpoint.ConnectionMode }); + + if (endpointIndex == 0) + { + ConsistencyLevel consistencyLevel = await client.GetAccountConsistencyLevelAsync(); + Assert.AreEqual(ConsistencyLevel.Eventual, consistencyLevel, "Only account with eventual consistency is supported by this test."); + } + + DatabaseResponse databaseResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => client.CreateDatabaseIfNotExistsAsync(database)); + if (endpointIndex == 0 && databaseResponse.StatusCode == HttpStatusCode.OK) + { + await databaseResponse.Database.DeleteAsync(); + databaseResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => client.CreateDatabaseIfNotExistsAsync(database)); + } + + HttpStatusCode expectedStatus = endpointIndex == 0 ? HttpStatusCode.Created : HttpStatusCode.OK; + Assert.AreEqual(expectedStatus, databaseResponse.StatusCode, + $"Endpoint#: {endpointIndex}, Endpoint : {endpoint.Url}. CreateDatabaseIfNotExistsAsync received unexpected response."); + + ContainerResponse containerResponse = await this.ExecuteOperationWithRetry( + MaxRetries, + () => databaseResponse.Database.CreateContainerIfNotExistsAsync( + new ContainerProperties(collection, "/pk") + { + ConflictResolutionPolicy = new ConflictResolutionPolicy() { Mode = ConflictResolutionMode.Custom } + })); + Assert.AreEqual(expectedStatus, databaseResponse.StatusCode, + $"Endpoint#: {endpointIndex}, Endpoint : {endpoint.Url}. CreateContainerIfNotExistsAsync received unexpected response."); + + clients.Add((client, containerResponse.Container)); + endpointIndex++; + } + + return clients; + } + + private async Task ExecuteOperationWithRetry(int maxRetryCount, Func> operation, Func shouldRetryWithoutException = null) + { + for (int i = 0; i < maxRetryCount; i++) + { + try + { + T result = await operation(); + if (shouldRetryWithoutException != null && shouldRetryWithoutException(result)) + { + if (i + 1 < maxRetryCount) + { + await Task.Delay(i * 1000); + continue; + } + + break; + } + + return result; + } + catch (Exception ex) + { + Console.WriteLine($"Attempt {i + 1}. Max Retries {maxRetryCount}. Exception: {ex}."); + if (i + 1 < maxRetryCount) + { + Thread.Sleep(i * 1000); + } + else + { + throw; + } + } + } + + throw new InvalidOperationException($"Operation failed after retries!"); + } + } +} diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs index 9eecd81e30..2074902249 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Query/SanityQueryTests.cs @@ -569,105 +569,6 @@ await QueryTestsBase.RunQueryAsync( } } - [TestMethod] - public async Task TestTryExecuteQuery() - { - await this.CreateIngestQueryDeleteAsync( - ConnectionModes.Direct | ConnectionModes.Gateway, - CollectionTypes.SinglePartition, - QueryTestsBase.NoDocuments, - this.TestTryExecuteQueryHelper); - } - - private async Task TestTryExecuteQueryHelper( - Container container, - IReadOnlyList documents) - { - ContainerInternal conatinerCore = (ContainerInlineCore)container; - foreach (int maxDegreeOfParallelism in new int[] { 1, 100 }) - { - foreach (int maxItemCount in new int[] { 10, 100 }) - { - foreach ((string query, QueryFeatures queryFeatures, bool canSupportExpected) in new Tuple[] - { - new Tuple("SELECT * FROM c", QueryFeatures.None, true), - new Tuple("SELECT * FROM c ORDER BY c._ts", QueryFeatures.None, false), - new Tuple("SELECT * FROM c ORDER BY c._ts", QueryFeatures.OrderBy, true), - }) - { - string continuationToken = null; - do - { - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: queryFeatures, - queryDefinition: new QueryDefinition(query), - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = maxDegreeOfParallelism, - MaxItemCount = maxItemCount, - }, - feedRangeInternal: null, - continuationToken: continuationToken, - geospatialType: Cosmos.GeospatialType.Geography); - - if (canSupportExpected) - { - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanIsSupportedResult); - } - else - { - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanNotSupportedResult); - } - - if (canSupportExpected) - { - ContainerInternal.QueryPlanIsSupportedResult queryPlanIsSupportedResult = (ContainerInternal.QueryPlanIsSupportedResult)tryExecuteQueryResult; - ResponseMessage cosmosQueryResponse = await queryPlanIsSupportedResult.QueryIterator.ReadNextAsync(); - continuationToken = cosmosQueryResponse.ContinuationToken; - } - } while (continuationToken != null); - } - } - } - - { - // Test the syntax error case - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: QueryFeatures.None, - queryDefinition: new QueryDefinition("This is not a valid query."), - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = 1, - MaxItemCount = 1, - }, - feedRangeInternal: null, - continuationToken: null, - geospatialType: Cosmos.GeospatialType.Geography); - - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.FailedToGetQueryPlanResult); - } - - { - // Test that the force passthrough mechanism works - ContainerInternal.TryExecuteQueryResult tryExecuteQueryResult = await conatinerCore.TryExecuteQueryAsync( - supportedQueryFeatures: QueryFeatures.None, // Not supporting any features - queryDefinition: new QueryDefinition("SELECT VALUE [{\"item\": {\"sum\": SUM(c.blah), \"count\": COUNT(c.blah)}}] FROM c"), // Query has aggregates - requestOptions: new QueryRequestOptions() - { - MaxConcurrency = 1, - MaxItemCount = 1, - }, - feedRangeInternal: new FeedRangePartitionKeyRange("0"), // filtering on a PkRangeId. - continuationToken: null, - geospatialType: Cosmos.GeospatialType.Geography); - - Assert.IsTrue(tryExecuteQueryResult is ContainerInternal.QueryPlanIsSupportedResult); - ContainerInternal.QueryPlanIsSupportedResult queryPlanIsSupportedResult = (ContainerInternal.QueryPlanIsSupportedResult)tryExecuteQueryResult; - ResponseMessage response = await queryPlanIsSupportedResult.QueryIterator.ReadNextAsync(); - Assert.IsTrue(response.IsSuccessStatusCode, response.ErrorMessage); - } - } - [TestMethod] public async Task TestMalformedPipelinedContinuationToken() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs index 762bbbd945..359bc07715 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/QueryTests.cs @@ -2135,12 +2135,12 @@ private void TestContinuationLimitHeaders(Database database, bool partitionedCol { if (!(e.InnerException is DocumentClientException exception)) { - throw e; + throw; } if (exception.StatusCode != HttpStatusCode.BadRequest) { - throw e; + throw; } Assert.IsTrue(exception.Message.Contains("continuation token limit specified is not large enough")); @@ -2159,12 +2159,12 @@ private void TestContinuationLimitHeaders(Database database, bool partitionedCol { if (!(e.InnerException is DocumentClientException exception)) { - throw e; + throw; } if (exception.StatusCode != HttpStatusCode.BadRequest) { - throw e; + throw; } Assert.IsTrue(exception.Message.Contains("Please pass in a valid continuation token size limit which must be a positive integer")); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs index c43a1aaf79..9d2d56ef55 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.EmulatorTests/Utils/TestCommon.cs @@ -144,10 +144,11 @@ internal static CosmosClient CreateCosmosClient( if(enableDistributingTracing) { - cosmosClientBuilder.WithDistributedTracingOptions(new DistributedTracingOptions() + // TODO: Check with Sourabh for potential fixes. + /*cosmosClientBuilder.WithDistributedTracingOptions(new DistributedTracingOptions() { LatencyThresholdForDiagnosticEvent = TimeSpan.FromMilliseconds(0) - }); + });*/ } return cosmosClientBuilder.Build(); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs index 334fc74ecf..0e10faf438 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Performance.Tests/Benchmarks/StopwatchAllocationsBenchmark.cs @@ -39,12 +39,16 @@ public void ValueStopwatchBoxedAsField() private class StopwatchHolder { +#pragma warning disable CS0414 // Remove unread private members private readonly Stopwatch stopwatch = new Stopwatch(); +#pragma warning restore CS0414 // Remove unread private members } private class ValueStopwatchHolder { +#pragma warning disable CS0414 // Remove unread private members private readonly ValueStopwatch stopwatch = new ValueStopwatch(); +#pragma warning restore CS0414 // Remove unread private members } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs index 0851952f40..cf1c739388 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ClientRetryPolicyTests.cs @@ -47,7 +47,7 @@ public void MultimasterMetadataWriteRetryTest() multimasterMetadataWriteRetryTest: true); - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery, new RetryOptions()); + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery, false); //Creates a metadata write request DocumentServiceRequest request = this.CreateRequest(false, true); @@ -102,8 +102,8 @@ public void Http503SubStatusHandelingTests(int testCode) isPreferredLocationsListEmpty: true); //Create Retry Policy - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery, new RetryOptions()); - + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(endpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery, false); + CancellationToken cancellationToken = new CancellationToken(); Exception serviceUnavailableException = new Exception(); Mock nameValueCollection = new Mock(); @@ -216,8 +216,8 @@ private async Task ValidateConnectTimeoutTriggersClientRetryPolicy( replicatedResourceClient.GoneAndRetryWithRetryTimeoutInSecondsOverride = 1; this.partitionKeyRangeLocationCache = GlobalPartitionEndpointManagerNoOp.Instance; - - ClientRetryPolicy retryPolicy = new ClientRetryPolicy(mockDocumentClientContext.GlobalEndpointManager, this.partitionKeyRangeLocationCache, enableEndpointDiscovery: true, new RetryOptions()); + + ClientRetryPolicy retryPolicy = new ClientRetryPolicy(mockDocumentClientContext.GlobalEndpointManager, this.partitionKeyRangeLocationCache, new RetryOptions(), enableEndpointDiscovery: true, isPertitionLevelFailoverEnabled: false); INameValueCollection headers = new DictionaryNameValueCollection(); headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.BoundedStaleness.ToString()); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs index 6c71504738..f0e127495a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcement.cs @@ -130,7 +130,7 @@ private static string GenerateNameWithFieldAttributes(FieldInfo fieldInfo) $"{nameof(fieldInfo.IsStatic)}:{(fieldInfo.IsStatic ? bool.TrueString : bool.FalseString)};"; } - private static TypeTree BuildTypeTree(TypeTree root, Type[] types) + private static TypeTree BuildTypeTree(TypeTree root, Type[] types, BindingFlags bindingflags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) { IEnumerable subclassTypes = types.Where((type) => type.IsSubclassOf(root.Type)).OrderBy(o => o.FullName, invariantComparer); foreach (Type subclassType in subclassTypes) @@ -139,7 +139,7 @@ private static TypeTree BuildTypeTree(TypeTree root, Type[] types) } IEnumerable> memberInfos = - root.Type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + root.Type.GetMembers(bindingflags) .Select(memberInfo => new KeyValuePair($"{memberInfo}{string.Join("-", ContractEnforcement.RemoveDebugSpecificAttributes(memberInfo.CustomAttributes))}", memberInfo)) .OrderBy(o => o.Key, invariantComparer); foreach (KeyValuePair memberInfo in memberInfos) @@ -203,6 +203,18 @@ public static void ValidateContractContainBreakingChanges( ContractEnforcement.ValidateJsonAreSame(localJson, baselineJson); } + public static void ValidateTelemetryContractContainBreakingChanges( + string dllName, + string baselinePath, + string breakingChangesPath) + { + string localTelemetryJson = GetCurrentTelemetryContract(dllName); + File.WriteAllText($"Contracts/{breakingChangesPath}", localTelemetryJson); + + string telemetryBaselineJson = GetBaselineContract(baselinePath); + ContractEnforcement.ValidateJsonAreSame(localTelemetryJson, telemetryBaselineJson); + } + public static void ValidatePreviewContractContainBreakingChanges( string dllName, string officialBaselinePath, @@ -238,6 +250,29 @@ public static string GetCurrentContract(string dllName) return localJson; } + public static string GetCurrentTelemetryContract(string dllName) + { + List nonTelemetryModels = new List + { + "AzureVMMetadata", + "Compute" + }; + + TypeTree locally = new TypeTree(typeof(object)); + Assembly assembly = ContractEnforcement.GetAssemblyLocally(dllName); + Type[] exportedTypes = assembly.GetTypes().Where(t => + t!= null && + t.Namespace != null && + t.Namespace.Contains("Microsoft.Azure.Cosmos.Telemetry.Models") && + !nonTelemetryModels.Contains(t.Name)) + .ToArray(); + + ContractEnforcement.BuildTypeTree(locally, exportedTypes, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly); + + string localJson = JsonConvert.SerializeObject(locally, Formatting.Indented); + return localJson; + } + public static string GetBaselineContract(string baselinePath) { string baselineFile = File.ReadAllText("Contracts/" + baselinePath); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs index 2e3a6457b3..c4fdacc939 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/ContractEnforcementTests.cs @@ -10,6 +10,7 @@ public class ContractEnforcementTests { private const string DllName = "Microsoft.Azure.Cosmos.Client"; private const string OfficialBaselinePath = "DotNetSDKAPI.json"; + private const string OfficialTelemetryBaselinePath = "DotNetSDKTelemetryAPI.json"; #if PREVIEW [TestMethod] @@ -30,6 +31,15 @@ public void ContractChanges() baselinePath: OfficialBaselinePath, breakingChangesPath: "DotNetSDKAPIChanges.json"); } + + [TestMethod] + public void TelemetryContractChanges() + { + ContractEnforcement.ValidateTelemetryContractContainBreakingChanges( + dllName: DllName, + baselinePath: OfficialTelemetryBaselinePath, + breakingChangesPath: "DotNetSDKTelemetryAPIChanges.json"); + } #endif [TestMethod] diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs index 2634ea1bc3..3300c84d60 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DirectContractTests.cs @@ -37,7 +37,6 @@ public void TestInteropTest() Assert.IsTrue(ServiceInteropWrapper.AssembliesExist.Value); string configJson = "{}"; - IntPtr provider; TryCatch tryCreateServiceProvider = QueryPartitionProvider.TryCreateServiceProvider(configJson); Assert.IsFalse(tryCreateServiceProvider.Failed); // Don't leak on tests diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json index 8c8d7d6ae1..46bdf1c170 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKAPI.json @@ -7986,6 +7986,18 @@ "Attributes": [], "MethodInfo": "System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] Properties;CanRead:True;CanWrite:True;System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object] get_Properties();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Properties(System.Collections.Generic.IReadOnlyDictionary`2[System.String,System.Object]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "System.Collections.Generic.List`1[System.String] ExcludeRegions": { + "Type": "Property", + "Attributes": [], + "MethodInfo": "System.Collections.Generic.List`1[System.String] ExcludeRegions;CanRead:True;CanWrite:True;System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[System.String] get_ExcludeRegions()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[System.String] get_ExcludeRegions();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "System.String get_IfMatchEtag()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ @@ -8029,6 +8041,13 @@ ], "MethodInfo": "Void set_CosmosThresholdOptions(Microsoft.Azure.Cosmos.CosmosThresholdOptions);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" }, + "Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_ExcludeRegions(System.Collections.Generic.List`1[System.String]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, "Void set_IfMatchEtag(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { "Type": "Method", "Attributes": [ diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json new file mode 100644 index 0000000000..bfc2bb20e6 --- /dev/null +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Contracts/DotNetSDKTelemetryAPI.json @@ -0,0 +1,356 @@ +{ + "Subclasses": { + "Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo;Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.ClientTelemetryProperties;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)[Newtonsoft.Json.JsonConstructorAttribute()]": { + "Type": "Constructor", + "Attributes": [ + "JsonConstructorAttribute" + ], + "MethodInfo": "[Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)[Newtonsoft.Json.JsonConstructorAttribute()], Void .ctor(System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Boolean], System.Collections.Generic.IReadOnlyList`1[System.String], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo], System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo], System.String)]" + }, + "Void Write(Newtonsoft.Json.JsonWriter)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void Write(Newtonsoft.Json.JsonWriter);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double])": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double]), Void .ctor(System.String, System.String, Double, Int64, Int64, Int64, System.Collections.Generic.IReadOnlyDictionary`2[System.Double,System.Double])]" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;System.Object;IsAbstract:False;IsSealed:False;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": { + "Microsoft.Azure.Cosmos.Telemetry.Models.CacheRefreshInfo;Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + } + }, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 get_SubStatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 SubStatusCode[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"subStatusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "Int32 SubStatusCode;CanRead:True;CanWrite:False;Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo Copy()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Microsoft.Azure.Cosmos.Telemetry.Models.OperationInfo Copy();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_StatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] StatusCode[Newtonsoft.Json.JsonPropertyAttribute(PropertyName = \"statusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] StatusCode;CanRead:True;CanWrite:False;System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo), Void .ctor(System.String, System.Nullable`1[System.Boolean], System.String, System.String, System.String, System.String, System.String, System.Nullable`1[System.Int32], Int32, Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)]" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.RequestInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Boolean Equals(System.Object)": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Boolean Equals(System.Object);IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double GetP99Latency()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double GetP99Latency();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Double GetSampleCount()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Double GetSampleCount();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 get_SubStatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCode()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCode();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 GetHashCodeForSampler()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Int32 GetHashCodeForSampler();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Int32 SubStatusCode[Newtonsoft.Json.JsonPropertyAttribute(\"subStatusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "Int32 SubStatusCode;CanRead:True;CanWrite:True;Int32 get_SubStatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_SubStatusCode(Int32);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] Metrics[Newtonsoft.Json.JsonPropertyAttribute(\"metricInfo\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] Metrics;CanRead:True;CanWrite:True;System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo] get_Metrics();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] get_StatusCode()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.Nullable`1[System.Int32] StatusCode[Newtonsoft.Json.JsonPropertyAttribute(\"statusCode\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.Nullable`1[System.Int32] StatusCode;CanRead:True;CanWrite:True;System.Nullable`1[System.Int32] get_StatusCode();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_StatusCode(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String ContainerName[Newtonsoft.Json.JsonPropertyAttribute(\"containerName\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String ContainerName;CanRead:True;CanWrite:True;System.String get_ContainerName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_ContainerName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String DatabaseName[Newtonsoft.Json.JsonPropertyAttribute(\"databaseName\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String DatabaseName;CanRead:True;CanWrite:True;System.String get_DatabaseName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_DatabaseName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_ContainerName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_ContainerName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_DatabaseName()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_DatabaseName();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Operation()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Operation();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Resource()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Resource();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String get_Uri()[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "System.String get_Uri();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Operation[Newtonsoft.Json.JsonPropertyAttribute(\"operation\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Operation;CanRead:True;CanWrite:True;System.String get_Operation();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Operation(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Resource[Newtonsoft.Json.JsonPropertyAttribute(\"resource\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Resource;CanRead:True;CanWrite:True;System.String get_Resource();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Resource(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String ToString()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "System.String ToString();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "System.String Uri[Newtonsoft.Json.JsonPropertyAttribute(\"uri\")]": { + "Type": "Property", + "Attributes": [ + "JsonPropertyAttribute" + ], + "MethodInfo": "System.String Uri;CanRead:True;CanWrite:True;System.String get_Uri();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;Void set_Uri(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void .ctor()": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(), Void .ctor()]" + }, + "Void set_ContainerName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_ContainerName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_DatabaseName(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_DatabaseName(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Metrics(System.Collections.Generic.List`1[Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Operation(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Operation(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Resource(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Resource(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_StatusCode(System.Nullable`1[System.Int32])[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_StatusCode(System.Nullable`1[System.Int32]);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_SubStatusCode(Int32)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_SubStatusCode(Int32);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void set_Uri(System.String)[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]": { + "Type": "Method", + "Attributes": [ + "CompilerGeneratedAttribute" + ], + "MethodInfo": "Void set_Uri(System.String);IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} + }, + "Microsoft.Azure.Cosmos.Telemetry.Models.SystemInfo;System.Object;IsAbstract:False;IsSealed:True;IsInterface:False;IsEnum:False;IsClass:True;IsValueType:False;IsNested:False;IsGenericType:False;IsSerializable:True": { + "Subclasses": {}, + "Members": { + "Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)": { + "Type": "Constructor", + "Attributes": [], + "MethodInfo": "[Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo), Void .ctor(Microsoft.Azure.Cosmos.Telemetry.Models.MetricInfo)]" + } + }, + "NestedTypes": {} + } + }, + "Members": { + "System.Object MemberwiseClone()[System.Runtime.CompilerServices.NullableContextAttribute((Byte)1)]-[System.Runtime.CompilerServices.IntrinsicAttribute()]": { + "Type": "Method", + "Attributes": [ + "IntrinsicAttribute", + "NullableContextAttribute" + ], + "MethodInfo": "System.Object MemberwiseClone();IsAbstract:False;IsStatic:False;IsVirtual:False;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + }, + "Void Finalize()": { + "Type": "Method", + "Attributes": [], + "MethodInfo": "Void Finalize();IsAbstract:False;IsStatic:False;IsVirtual:True;IsGenericMethod:False;IsConstructor:False;IsFinal:False;" + } + }, + "NestedTypes": {} +} \ No newline at end of file diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs index 151e0690a8..9834f39a47 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosBadReplicaTests.cs @@ -71,11 +71,11 @@ public async Task TestGoneFromServiceScenarioAsync( "44444444444444444", }; - HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( - replicaIds1, - partitionKeyRanges.First(), - "eastus", - cRid); + HttpResponseMessage replicaSet1 = MockSetupsHelper.CreateAddresses( + replicaIds1, + partitionKeyRanges.First(), + "eastus", + cRid); // One replica changed on the refresh List replicaIds2 = new List() @@ -176,6 +176,10 @@ public async Task TestGoneFromServiceScenarioAsync( mockTransportClient.VerifyAll(); mockHttpHandler.VerifyAll(); + mockTransportClient + .Setup(x => x.OpenConnectionAsync(It.IsAny())) + .Returns(Task.CompletedTask); + Documents.TransportAddressUri failedReplica = urisVisited.First(); // With replica validation enabled in preview mode, the failed replica will be validated as a part of the flow, diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs index 9390de7f0d..5a230b139c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientOptionsUnitTests.cs @@ -11,7 +11,6 @@ namespace Microsoft.Azure.Cosmos.Tests using System.Linq; using System.Net; using System.Net.Http; - using Cosmos.Telemetry; using global::Azure.Core; using Microsoft.Azure.Cosmos.Fluent; using Microsoft.Azure.Documents; @@ -116,8 +115,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) .WithBulkExecution(true) .WithSerializerOptions(cosmosSerializerOptions) - .WithConsistencyLevel(consistencyLevel) - .WithPartitionLevelFailoverEnabled(); + .WithConsistencyLevel(consistencyLevel); cosmosClient = cosmosClientBuilder.Build(new MockDocumentClient()); clientOptions = cosmosClient.ClientOptions; @@ -140,7 +138,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.IsTrue(object.ReferenceEquals(webProxy, clientOptions.WebProxy)); Assert.IsTrue(clientOptions.AllowBulkExecution); Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); - Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); + Assert.IsFalse(clientOptions.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.HasValue && clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); //Verify GetConnectionPolicy returns the correct values @@ -155,7 +153,7 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, policy.RetryOptions.MaxRetryAttemptsOnThrottledRequests); Assert.AreEqual((int)maxRetryWaitTime.TotalSeconds, policy.RetryOptions.MaxRetryWaitTimeInSeconds); Assert.AreEqual((Documents.ConsistencyLevel)consistencyLevel, clientOptions.GetDocumentsConsistencyLevel()); - Assert.IsTrue(policy.EnablePartitionLevelFailover); + Assert.IsFalse(policy.EnablePartitionLevelFailover); Assert.IsTrue(clientOptions.EnableAdvancedReplicaSelectionForTcp.Value); IReadOnlyList preferredLocations = new List() { Regions.AustraliaCentral, Regions.AustraliaCentral2 }; @@ -206,6 +204,147 @@ public void VerifyCosmosConfigurationPropertiesGetUpdated() CollectionAssert.AreEqual(preferredLocations.ToArray(), policy.PreferredLocations.ToArray()); } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is missing, then the client + /// initialization should throw an argument exception and fail. This should hold true for both environment variable and CosmosClientOptions. + /// + [TestMethod] + [Owner("dkunda")] + [DataRow(true, DisplayName = "Validate that when enevironment variable is used to enable PPAF, the outcome of the test should be same.")] + [DataRow(false, DisplayName = "Validate that when CosmosClientOptions is used to enable PPAF, the outcome of the test should be same.")] + public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredRegionsNotSet_ShouldThrowArgumentException(bool useEnvironmentVariable) + { + try + { + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, "True"); + } + + string endpoint = AccountEndpoint; + string key = MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey; + TimeSpan requestTimeout = TimeSpan.FromDays(1); + string userAgentSuffix = "testSuffix"; + RequestHandler preProcessHandler = new TestHandler(); + ApiType apiType = ApiType.Sql; + int maxRetryAttemptsOnThrottledRequests = 9999; + TimeSpan maxRetryWaitTime = TimeSpan.FromHours(6); + CosmosSerializationOptions cosmosSerializerOptions = new CosmosSerializationOptions() + { + IgnoreNullValues = true, + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase, + }; + + Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + CosmosClientBuilder cosmosClientBuilder = new( + accountEndpoint: endpoint, + authKeyOrResourceToken: key); + + cosmosClientBuilder + .WithConnectionModeDirect() + .WithRequestTimeout(requestTimeout) + .WithApplicationName(userAgentSuffix) + .AddCustomHandlers(preProcessHandler) + .WithApiType(apiType) + .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) + .WithSerializerOptions(cosmosSerializerOptions) + .WithConsistencyLevel(consistencyLevel); + + if (!useEnvironmentVariable) + { + cosmosClientBuilder + .WithPartitionLevelFailoverEnabled(); + } + + ArgumentException exception = Assert.ThrowsException(() => cosmosClientBuilder.Build()); + + Assert.AreEqual( + expected: "ApplicationPreferredRegions is required when EnablePartitionLevelFailover is enabled.", + actual: exception.Message); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, null); + } + } + + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is provided, then the client + /// initialization should be successful. This holds true for both environment variable and CosmosClientOptions. + /// + [TestMethod] + [Owner("dkunda")] + [DataRow(true, DisplayName = "Validate that when enevironment variable is used to enable PPAF, the outcome of the test should be same.")] + [DataRow(false, DisplayName = "Validate that when CosmosClientOptions is used to enable PPAF, the outcome of the test should be same.")] + public void CosmosClientOptions_WhenPartitionLevelFailoverEnabledAndPreferredRegionsSet_ShouldInitializeSuccessfully(bool useEnvironmentVariable) + { + try + { + if (useEnvironmentVariable) + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, "True"); + } + + string endpoint = AccountEndpoint; + string key = MockCosmosUtil.RandomInvalidCorrectlyFormatedAuthKey; + TimeSpan requestTimeout = TimeSpan.FromDays(1); + string userAgentSuffix = "testSuffix"; + RequestHandler preProcessHandler = new TestHandler(); + ApiType apiType = ApiType.Sql; + int maxRetryAttemptsOnThrottledRequests = 9999; + TimeSpan maxRetryWaitTime = TimeSpan.FromHours(6); + CosmosSerializationOptions cosmosSerializerOptions = new CosmosSerializationOptions() + { + IgnoreNullValues = true, + PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase, + }; + + Cosmos.ConsistencyLevel consistencyLevel = Cosmos.ConsistencyLevel.ConsistentPrefix; + CosmosClientBuilder cosmosClientBuilder = new( + accountEndpoint: endpoint, + authKeyOrResourceToken: key); + + cosmosClientBuilder + .WithConnectionModeDirect() + .WithRequestTimeout(requestTimeout) + .WithApplicationName(userAgentSuffix) + .AddCustomHandlers(preProcessHandler) + .WithApiType(apiType) + .WithThrottlingRetryOptions(maxRetryWaitTime, maxRetryAttemptsOnThrottledRequests) + .WithSerializerOptions(cosmosSerializerOptions) + .WithConsistencyLevel(consistencyLevel) + .WithPartitionLevelFailoverEnabled() + .WithApplicationPreferredRegions( + new List() + { + Regions.NorthCentralUS, + Regions.WestUS, + Regions.EastAsia, + }); + + CosmosClientOptions clientOptions = cosmosClientBuilder.Build().ClientOptions; + + Assert.AreEqual(ConnectionMode.Direct, clientOptions.ConnectionMode); + Assert.AreEqual(requestTimeout, clientOptions.RequestTimeout); + Assert.AreEqual(userAgentSuffix, clientOptions.ApplicationName); + Assert.AreEqual(preProcessHandler, clientOptions.CustomHandlers[0]); + Assert.AreEqual(apiType, clientOptions.ApiType); + Assert.AreEqual(maxRetryAttemptsOnThrottledRequests, clientOptions.MaxRetryAttemptsOnRateLimitedRequests); + Assert.AreEqual(maxRetryWaitTime, clientOptions.MaxRetryWaitTimeOnRateLimitedRequests); + Assert.AreEqual(cosmosSerializerOptions.IgnoreNullValues, clientOptions.SerializerOptions.IgnoreNullValues); + Assert.AreEqual(cosmosSerializerOptions.PropertyNamingPolicy, clientOptions.SerializerOptions.PropertyNamingPolicy); + Assert.AreEqual(cosmosSerializerOptions.Indented, clientOptions.SerializerOptions.Indented); + Assert.IsFalse(clientOptions.AllowBulkExecution); + Assert.AreEqual(consistencyLevel, clientOptions.ConsistencyLevel); + Assert.IsTrue(clientOptions.EnablePartitionLevelFailover); + Assert.IsNotNull(clientOptions.ApplicationPreferredRegions); + } + finally + { + Environment.SetEnvironmentVariable(ConfigurationManager.PartitionLevelFailoverEnabled, null); + } + } + [TestMethod] public void VerifyConsisentencyLevels() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs index 2bb48fc75b..575fe4ae01 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosConflictTests.cs @@ -5,11 +5,16 @@ namespace Microsoft.Azure.Cosmos.Tests { using System; + using System.IO; + using System.Net; + using System.Text; using System.Threading; using System.Threading.Tasks; - using Microsoft.Azure.Documents; + using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Handlers; using Microsoft.Azure.Cosmos.Routing; + using Microsoft.Azure.Cosmos.Tracing; + using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; using Newtonsoft.Json.Linq; @@ -33,6 +38,43 @@ public async Task ConflictsFeedSetsPartitionKeyRangeIdentity() } } + [TestMethod] + public async Task QueryConflicts() + { + ContainerInternal container = CosmosConflictTests.GetMockedContainer((request, cancellationToken) => { + Assert.AreEqual(ResourceType.Conflict, request.ResourceType); + ResponseMessage responseMessage = new ResponseMessage(HttpStatusCode.OK) + { + Content = new MemoryStream(Encoding.UTF8.GetBytes(@"{ ""Conflicts"": [{ ""id"": ""Test""}]}")) + }; + return Task.FromResult(responseMessage); + }); + + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator(); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator("SELECT * FROM c"); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + { + FeedIterator iterator = container.Conflicts.GetConflictQueryIterator( + queryText: "SELECT * FROM c", + requestOptions: new QueryRequestOptions { MaxItemCount = 1 }); + while (iterator.HasMoreResults) + { + FeedResponse responseMessage = await iterator.ReadNextAsync(); + } + } + } + [TestMethod] public async Task ReadCurrentGetsCorrectRID() { diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs index 03fdb84ead..09401bda13 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosHttpClientCoreTests.cs @@ -243,7 +243,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio public async Task Retry3TimesOnDefaultPolicyTestAsync() { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { count++; @@ -268,7 +268,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio cancellationToken: default); } } - catch (Exception ex) + catch (Exception) { //Ignore the exception } @@ -283,7 +283,7 @@ public async Task HttpTimeoutThrow503TestAsync() async Task TestScenarioAsync(HttpMethod method, ResourceType resourceType, HttpTimeoutPolicy timeoutPolicy, Type expectedException, int expectedNumberOfRetrys) { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { count++; @@ -346,7 +346,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio public async Task NoRetryOnNoRetryPolicyTestAsync() { int count = 0; - async Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) + Task sendFunc(HttpRequestMessage request, CancellationToken cancellationToken) { if(count == 0) { @@ -355,7 +355,6 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio count++; throw new OperationCanceledException("API with exception"); - } DocumentClientEventSource eventSource = DocumentClientEventSource.Instance; @@ -375,7 +374,7 @@ async Task sendFunc(HttpRequestMessage request, Cancellatio cancellationToken: default); } } - catch (Exception ex) + catch (Exception) { //Ignore the exception } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs index c855599465..fded897e42 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayAddressCacheTests.cs @@ -965,7 +965,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat { // Arrange. ManualResetEvent manualResetEvent = new(initialState: false); - Mock mockHttpHandler = new (MockBehavior.Strict); + Mock mockHttpHandler = new(MockBehavior.Strict); string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; @@ -987,12 +987,12 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat newAddress, })); - FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( failingIndexes: new HashSet(), manualResetEvent: manualResetEvent); - HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); - GatewayAddressCache cache = new ( + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Tcp, this.mockTokenProvider.Object, @@ -1023,10 +1023,10 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat manualResetEvent: manualResetEvent, shouldReset: true); - // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. + // Because the Unknown Replicas are not validated, the health status should remain as unknown. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Connected, + expected: TransportAddressHealthState.HealthStatus.Unknown, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( @@ -1076,17 +1076,17 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( addressInfo: addressInfo, - numberOfConnectedReplicas: 2, - numberOfUnknownReplicas: 1, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 3, numberOfUnhealthyPendingReplicas: 1, numberOfUnhealthyReplicas: 0); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, - expectedTotalHandlerInvocationCount: 2, - expectedTotalReceivedAddressesCount: 6, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 1, + expectedTotalSuccessAddressesToOpenCount: 1); } /// @@ -1099,7 +1099,7 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabled_ShouldValidat public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUriExistsForOneMinute_ShouldForceRefreshUnhealthyReplicas() { // Arrange. - ManualResetEvent manualResetEvent = new (initialState: false); + ManualResetEvent manualResetEvent = new(initialState: false); Mock mockHttpHandler = new(MockBehavior.Strict); string oldAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; string newAddress = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; @@ -1129,15 +1129,15 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr newAddress, })); - FakeOpenConnectionHandler fakeOpenConnectionHandler = new ( + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( failIndexesByAttempts: new Dictionary>() { - { 0, new HashSet() { 2 } } + { 0, new HashSet() { 1 } } }, manualResetEvent: manualResetEvent); - HttpClient httpClient = new (new HttpHandlerHelper(mockHttpHandler.Object)); - GatewayAddressCache cache = new ( + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Tcp, this.mockTokenProvider.Object, @@ -1178,14 +1178,14 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 0, - expectedTotalHandlerInvocationCount: 1, - expectedTotalReceivedAddressesCount: 4, - expectedTotalSuccessAddressesToOpenCount: 4); + expectedTotalHandlerInvocationCount: 0, + expectedTotalReceivedAddressesCount: 0, + expectedTotalSuccessAddressesToOpenCount: 0); - // Because the Unknown Replicas are now validated aggresively, the health status should be marked as connected. + // Because the Unknown Replicas are not validated, the health status should remain as unknown. Assert.IsNotNull(refreshedUri); Assert.AreEqual( - expected: TransportAddressHealthState.HealthStatus.Connected, + expected: TransportAddressHealthState.HealthStatus.Unknown, actual: refreshedUri.GetCurrentHealthState().GetHealthStatus()); Assert.AreEqual(4, addressInfo.AllAddresses.Count); @@ -1228,17 +1228,17 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.ValidateHealthStatesInDiagnostics( addressInfo: addressInfo, - numberOfConnectedReplicas: 2, - numberOfUnknownReplicas: 1, + numberOfConnectedReplicas: 0, + numberOfUnknownReplicas: 3, numberOfUnhealthyPendingReplicas: 1, numberOfUnhealthyReplicas: 0); GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 2, - expectedTotalReceivedAddressesCount: 6, - expectedTotalSuccessAddressesToOpenCount: 5); + expectedTotalHandlerInvocationCount: 1, + expectedTotalReceivedAddressesCount: 1, + expectedTotalSuccessAddressesToOpenCount: 0); // A delay of 2 minute was added to make the replica unhealthy for more than one minute. This // will make sure the unhealthy replica gets a chance to re-validate it's health status. @@ -1263,9 +1263,9 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 3, - expectedTotalReceivedAddressesCount: 7, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 2, + expectedTotalSuccessAddressesToOpenCount: 1); addressInfo = await cache.TryGetAddressesAsync( request: request, @@ -1293,9 +1293,140 @@ public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndUnhealthyUr GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( fakeOpenConnectionHandler: fakeOpenConnectionHandler, expectedTotalFailedAddressesToOpenCount: 1, - expectedTotalHandlerInvocationCount: 3, - expectedTotalReceivedAddressesCount: 7, - expectedTotalSuccessAddressesToOpenCount: 6); + expectedTotalHandlerInvocationCount: 2, + expectedTotalReceivedAddressesCount: 2, + expectedTotalSuccessAddressesToOpenCount: 1); + } + + /// + /// Test to validate that when replica validation is enabled and there exists a replica such that it remained unhealthy for a period of one minute or + /// more, then even though a force refresh is not requested, the unhealthy replicas at least get a chance to re-validate it's status by the + /// on-demand async non-blocking cache refresh flow and eventually marks itself as healthy once the open connection attempt is successful. The purpose + /// of this test to validate the above scenario with high number of concurrent execution and validate that the concurrent executions doesn't create an + /// unbounded number of tasks and the task creation is limited to just one, thus reducing the pressure on the task scheduler drammatically. + /// + [TestMethod] + [Owner("dkunda")] + public async Task TryGetAddressesAsync_WhenReplicaVlidationEnabledAndCSListenerMarksReplicaUnhealthyWithParallelInvocation_ShouldValidateUnhealthyReplicasOnce() + { + // Arrange. + int maxIteration = 2; + ManualResetEvent manualResetEvent = new(initialState: false); + Mock mockHttpHandler = new(MockBehavior.Strict); + string oldAddress = "rntbd://dummytenant.documents.azure.com:14004/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/4s"; + string newAddress = "rntbd://dummytenant.documents.azure.com:14004/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/5s"; + string addressTobeMarkedUnhealthy = "rntbd://dummytenant.documents.azure.com:14002/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/2s"; + mockHttpHandler.SetupSequence(x => x.SendAsync( + It.IsAny(), + It.IsAny())) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + oldAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })) + .Returns(MockCosmosUtil.CreateHttpResponseOfAddresses(new List() + { + "rntbd://dummytenant.documents.azure.com:14001/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/1p", + addressTobeMarkedUnhealthy, + "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/3s", + newAddress, + })); + + FakeOpenConnectionHandler fakeOpenConnectionHandler = new( + failIndexesByAttempts: new Dictionary>(), + manualResetEvent: manualResetEvent, + openConnectionDelayInSeconds: 1); + + HttpClient httpClient = new(new HttpHandlerHelper(mockHttpHandler.Object)); + GatewayAddressCache cache = new( + new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), + Documents.Client.Protocol.Tcp, + this.mockTokenProvider.Object, + this.mockServiceConfigReader.Object, + MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), + openConnectionsHandler: fakeOpenConnectionHandler, + suboptimalPartitionForceRefreshIntervalInSeconds: 2, + enableTcpConnectionEndpointRediscovery: true, + replicaAddressValidationEnabled: true); + + DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid); + + // Act and Assert. + PartitionAddressInformation addressInfo = default; + TransportAddressUri refreshedUri = default; + + for (int iterationIndex = 1; iterationIndex <= maxIteration; iterationIndex++) + { + List openConnectionTasks = new(); + addressInfo = await cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None); + + // Mimic the Connection State Listener based approach to mark a replica to unhealthy. + await cache.MarkAddressesToUnhealthyAsync( + new ServerKey( + new Uri( + uriString: addressTobeMarkedUnhealthy))); + + refreshedUri = addressInfo + .Get(Protocol.Tcp)? + .ReplicaTransportAddressUris + .Single(x => x.ToString().Equals(addressTobeMarkedUnhealthy)); + + ReflectionUtils.AddMinuteToDateTimeFieldUsingReflection( + objectName: refreshedUri.GetCurrentHealthState(), + fieldName: "lastUnhealthyTimestamp", + delayInMinutes: -2 * iterationIndex); + + for (int j = 0; j < 500 * iterationIndex; j++) + { + openConnectionTasks + .Add( + cache.TryGetAddressesAsync( + request: request, + partitionKeyRangeIdentity: this.testPartitionKeyRangeIdentity, + serviceIdentity: this.serviceIdentity, + forceRefreshPartitionAddresses: false, + cancellationToken: CancellationToken.None)); + } + + // awaits for the parallel execution to finish. + await Task.WhenAll(openConnectionTasks); + + // This assertion validates that there are no extra tasks created in the thread pool. + Assert.AreEqual(0, ThreadPool.PendingWorkItemCount); + + // Waits until a completion signal from the background task is received. + GatewayAddressCacheTests.WaitForManualResetEventSignal( + manualResetEvent: manualResetEvent, + shouldReset: true); + + GatewayAddressCacheTests.AssertOpenConnectionHandlerAttributes( + fakeOpenConnectionHandler: fakeOpenConnectionHandler, + expectedTotalFailedAddressesToOpenCount: 0, + expectedTotalHandlerInvocationCount: iterationIndex, + expectedTotalReceivedAddressesCount: iterationIndex, + expectedTotalSuccessAddressesToOpenCount: iterationIndex); + } } /// @@ -1577,11 +1708,13 @@ public FakeOpenConnectionHandler( public FakeOpenConnectionHandler( Dictionary> failIndexesByAttempts, - ManualResetEvent manualResetEvent = null) + ManualResetEvent manualResetEvent = null, + int openConnectionDelayInSeconds = 0) { this.useAttemptBasedFailingIndexs = true; this.failIndexesByAttempts = failIndexesByAttempts; this.manualResetEvent = manualResetEvent; + this.openConnectionDelayInSeconds = openConnectionDelayInSeconds; } public int GetTotalSuccessfulInvocationCount() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs index e16f176e61..fd9a8a3efd 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/GatewayStoreModelTest.cs @@ -175,11 +175,13 @@ public async Task PassesPropertiesFromDocumentServiceRequest() Func> sendFunc = request => { +#pragma warning disable CS0618 // Type or member is obsolete Assert.AreEqual(properties.Count, request.Properties.Count); foreach (KeyValuePair item in properties) { Assert.AreEqual(item.Value, request.Properties[item.Key]); } +#pragma warning restore CS0618 // Type or member is obsolete return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK) ); }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs index 281e550d24..9d5e391748 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/InterfaceParityTest.cs @@ -24,6 +24,7 @@ public void TestAllPublicMethodsExistInIDocumentClient() string[] excludedMethods = new string[] { "OpenAsync", // exposed public methods. + "TryGetCachedAccountProperties", // currently only internal "get_PartitionResolvers", "get_ResourceTokens", // Obsolete getters. "ToString", "Equals", "GetHashCode", "GetType", "get_httpClient" }; diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs index 8273897374..06ed0d4026 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/LocationCacheTests.cs @@ -131,7 +131,7 @@ private async Task ValidateRetryOnSessionNotAvailabeWithEndpointDiscoveryDisable useMultipleWriteLocations: useMultipleWriteLocations, enableEndpointDiscovery: enableEndpointDiscovery, isPreferredLocationsListEmpty: isPreferredLocationsListEmpty); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { @@ -174,14 +174,16 @@ await BackoffRetryUtility.ExecuteAsync( } private ClientRetryPolicy CreateClientRetryPolicy( - bool enableEndpointDiscovery, + bool enableEndpointDiscovery, + bool partitionLevelFailoverEnabled, GlobalEndpointManager endpointManager) { return new ClientRetryPolicy( endpointManager, this.partitionKeyRangeLocationCache, - enableEndpointDiscovery, - new RetryOptions()); + new RetryOptions(), + enableEndpointDiscovery, + isPertitionLevelFailoverEnabled: partitionLevelFailoverEnabled); } [TestMethod] @@ -203,7 +205,7 @@ private async Task ValidateRetryOnSessionNotAvailabeWithDisableMultipleWriteLoca isPreferredLocationsListEmpty: isPreferredLocationsListEmpty); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: true, isMasterResourceType: false)) { @@ -281,7 +283,7 @@ private async Task ValidateRetryOnReadSessionNotAvailabeWithEnableMultipleWriteL preferedRegionListOverride: preferredList); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: true, isMasterResourceType: false)) { @@ -357,7 +359,7 @@ private async Task ValidateRetryOnWriteSessionNotAvailabeWithEnableMultipleWrite preferedRegionListOverride: preferredList); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: false, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: false, isMasterResourceType: false)) { @@ -429,7 +431,7 @@ public async Task ValidateRetryOnWriteForbiddenExceptionAsync() isPreferredLocationsListEmpty: false); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: false, isMasterResourceType: false)) { @@ -501,7 +503,7 @@ private async Task ValidateRetryOnDatabaseAccountNotFoundAsync(bool enableMultip isPreferredLocationsListEmpty: false); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); int expectedRetryCount = isReadRequest || enableMultipleWriteLocations ? 2 : 1; @@ -606,7 +608,7 @@ private async Task ValidateRetryOnHttpExceptionAsync(bool enableMultipleWriteLoc enforceSingleMasterSingleWriteLocation: true); endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, endpointManager: endpointManager); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { @@ -676,22 +678,22 @@ await BackoffRetryUtility.ExecuteAsync( } [DataTestMethod] - [DataRow(true, false, false, false, false, DisplayName = "Read request - Single master - no preferred locations - should NOT retry")] - [DataRow(false, false, false, false, false, DisplayName = "Write request - Single master - no preferred locations - should NOT retry")] - [DataRow(true, true, false, false, false, DisplayName = "Read request - Multi master - no preferred locations - should NOT retry")] - [DataRow(false, true, false, false, false, DisplayName = "Write request - Multi master - no preferred locations - should NOT retry")] - [DataRow(true, false, true, true, false, DisplayName = "Read request - Single master - with preferred locations - should retry")] - [DataRow(false, false, true, false, false, DisplayName = "Write request - Single master - with preferred locations - should NOT retry")] - [DataRow(true, true, true, true, false, DisplayName = "Read request - Multi master - with preferred locations - should retry")] - [DataRow(false, true, true, true, false, DisplayName = "Write request - Multi master - with preferred locations - should retry")] - [DataRow(true, false, false, false, true, DisplayName = "Read request - Single master - no preferred locations - should NOT retry")] - [DataRow(false, false, false, false, true, DisplayName = "Write request - Single master - no preferred locations - should NOT retry")] - [DataRow(true, true, false, false, true, DisplayName = "Read request - Multi master - no preferred locations - should NOT retry")] - [DataRow(false, true, false, false, true, DisplayName = "Write request - Multi master - no preferred locations - should NOT retry")] - [DataRow(true, false, true, true, true, DisplayName = "Read request - Single master - with preferred locations - should retry")] - [DataRow(false, false, true, false, true, DisplayName = "Write request - Single master - with preferred locations - should NOT retry")] - [DataRow(true, true, true, true, true, DisplayName = "Read request - Multi master - with preferred locations - should retry")] - [DataRow(false, true, true, true, true, DisplayName = "Write request - Multi master - with preferred locations - should retry")] + [DataRow(true, false, false, false, false, DisplayName = "Read request - Single master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(false, false, false, false, false, DisplayName = "Write request - Single master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, true, false, false, false, DisplayName = "Read request - Multi master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(false, true, false, false, false, DisplayName = "Write request - Multi master - no preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, false, true, true, false, DisplayName = "Read request - Single master - with preferred locations - without partition level failover - should retry")] + [DataRow(false, false, true, false, false, DisplayName = "Write request - Single master - with preferred locations - without partition level failover - should NOT retry")] + [DataRow(true, true, true, true, false, DisplayName = "Read request - Multi master - with preferred locations - without partition level failover - should retry")] + [DataRow(false, true, true, true, false, DisplayName = "Write request - Multi master - with preferred locations - without partition level failover - should retry")] + [DataRow(true, false, false, false, true, DisplayName = "Read request - Single master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, false, false, false, true, DisplayName = "Write request - Single master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(true, true, false, false, true, DisplayName = "Read request - Multi master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, true, false, false, true, DisplayName = "Write request - Multi master - no preferred locations - with partition level failover - should NOT retry")] + [DataRow(true, false, true, true, true, DisplayName = "Read request - Single master - with preferred locations - with partition level failover - should NOT retry")] + [DataRow(false, false, true, true, true, DisplayName = "Write request - Single master - with preferred locations - with partition level failover - should retry")] + [DataRow(true, true, true, true, true, DisplayName = "Read request - Multi master - with preferred locations - with partition level failover - should retry")] + [DataRow(false, true, true, true, true, DisplayName = "Write request - Multi master - with preferred locations - with partition level failover - should retry")] public async Task ClientRetryPolicy_ValidateRetryOnServiceUnavailable( bool isReadRequest, bool useMultipleWriteLocations, @@ -714,8 +716,9 @@ public async Task ClientRetryPolicy_ValidateRetryOnServiceUnavailable( preferedRegionListOverride: preferredList, enforceSingleMasterSingleWriteLocation: true); - endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); - ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, endpointManager); + endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); + + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery, partitionLevelFailoverEnabled: enablePartitionLevelFailover, endpointManager); using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) { @@ -767,11 +770,180 @@ await BackoffRetryUtility.ExecuteAsync( } } + [TestMethod] + [DataRow(true, true, true, DisplayName = "Read request - Multi master - with preferred locations")] + [DataRow(true, true, false, DisplayName = "Read request - Multi master - no preferred locations")] + [DataRow(true, false, true, DisplayName = "Read request - Single master - with preferred locations")] + [DataRow(true, false, false, DisplayName = "Read request - Single master - no preferred locations")] + [DataRow(false, true, true, DisplayName = "Write request - Multi master - with preferred locations")] + [DataRow(false, true, false, DisplayName = "Write request - Multi master - no preferred locations")] + [DataRow(false, false, true, DisplayName = "Write request - Single master - with preferred locations")] + [DataRow(false, false, false, DisplayName = "Write request - Single master - no preferred locations")] + public void VerifyRegionExcludedTest( + bool isReadRequest, + bool useMultipleWriteLocations, + bool usesPreferredLocations) + { + bool enableEndpointDiscovery = true; + + ReadOnlyCollection preferredList = usesPreferredLocations ? + isReadRequest ? + new List { + "location4", + "location2", + "location1" + }.AsReadOnly() : + new List { + "location3", + "location2", + "location1" + }.AsReadOnly() : + isReadRequest ? + new List() { + "default", + "location1", + "location2", + "location4" + }.AsReadOnly() : + new List() { + "default", + "location1", + "location2", + "location3" + }.AsReadOnly(); + + List> excludeRegionCases = isReadRequest ? + new List>() + { + new List {"default"}, new List {"default", "location1"}, new List {"default", "location2"}, new List {"default", "location4"}, + new List {"default", "location1", "location2"}, new List {"default", "location1", "location4"}, new List {"default", "location2", "location4"}, + new List {"default", "location1", "location2", "location4"}, new List { "location1" }, new List {"location1", "location2"}, + new List {"location1", "location4"}, new List {"location1", "location2", "location4"},new List { "location2" }, + new List {"location2", "location4"},new List { "location4" }, + } : + new List>() + { + new List {"default" }, new List {"default", "location1"}, new List {"default", "location2"}, new List {"default", "location3"}, + new List {"default", "location1", "location2"}, new List {"default", "location1", "location3"}, new List {"default", "location2", "location3"}, + new List {"default", "location1", "location2", "location3"}, new List { "location1" }, new List {"location1", "location2"}, + new List {"location1", "location3"}, new List {"location1", "location2", "location3"},new List { "location2" }, + new List {"location2", "location3"},new List { "location3" }, + }; + + foreach (List excludeRegions in excludeRegionCases) + { + using GlobalEndpointManager endpointManager = this.Initialize( + useMultipleWriteLocations: useMultipleWriteLocations, + enableEndpointDiscovery: enableEndpointDiscovery, + isPreferredLocationsListEmpty: false, + preferedRegionListOverride: preferredList, + enforceSingleMasterSingleWriteLocation: true, + isExcludeRegionsTest: true); + + endpointManager.InitializeAccountPropertiesAndStartBackgroundRefresh(this.databaseAccount); + ClientRetryPolicy retryPolicy = this.CreateClientRetryPolicy(enableEndpointDiscovery: true, partitionLevelFailoverEnabled: false, endpointManager: endpointManager); + + using (DocumentServiceRequest request = this.CreateRequest(isReadRequest: isReadRequest, isMasterResourceType: false)) + { + request.RequestContext.ExcludeRegions = excludeRegions; + + ReadOnlyCollection applicableEndpoints = endpointManager.GetApplicableEndpoints(request, isReadRequest); + + Uri endpoint = endpointManager.ResolveServiceEndpoint(request); + ReadOnlyCollection applicableRegions = this.GetApplicableRegions(isReadRequest, useMultipleWriteLocations, usesPreferredLocations, excludeRegions); + + Assert.AreEqual(applicableRegions.Count, applicableEndpoints.Count); + for(int i = 0; i < applicableRegions.Count; i++) + { + Assert.AreEqual(applicableRegions[i], applicableEndpoints[i]); + } + + Assert.AreEqual(applicableRegions[0], endpoint); + } + } + + } + + private ReadOnlyCollection GetApplicableRegions(bool isReadRequest, bool useMultipleWriteLocations, bool usesPreferredLocations, List excludeRegions) + { + if(!isReadRequest && !useMultipleWriteLocations) + { + return new List() {LocationCacheTests.DefaultEndpoint }.AsReadOnly(); + } + + Dictionary readWriteLocations = usesPreferredLocations ? + isReadRequest ? + new Dictionary() + { + {"location4", LocationCacheTests.Location4Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + } : + useMultipleWriteLocations ? + new Dictionary() + { + {"location3", LocationCacheTests.Location3Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + } : + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + } : + isReadRequest ? + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location4", LocationCacheTests.Location4Endpoint }, + } : + useMultipleWriteLocations ? + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint }, + {"location1", LocationCacheTests.Location1Endpoint }, + {"location2", LocationCacheTests.Location2Endpoint }, + {"location3", LocationCacheTests.Location3Endpoint }, + } : + new Dictionary() + { + {"default", LocationCacheTests.DefaultEndpoint} + }; + + List applicableRegions = new List(); + + foreach (string region in readWriteLocations.Keys) + { + if(!excludeRegions.Contains(region)) + { + applicableRegions.Add(readWriteLocations[region]); + } + } + + if (applicableRegions.Count == 0) + { + applicableRegions.Add(LocationCacheTests.DefaultEndpoint); + } + + return applicableRegions.AsReadOnly(); + } + private static AccountProperties CreateDatabaseAccount( bool useMultipleWriteLocations, - bool enforceSingleMasterSingleWriteLocation) + bool enforceSingleMasterSingleWriteLocation, + bool isExcludeRegionsTest = false) { - Collection writeLocations = new Collection() + Collection writeLocations = isExcludeRegionsTest ? + + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } }, + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location3", Endpoint = LocationCacheTests.Location3Endpoint.ToString() } }, + } : + new Collection() { { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, @@ -783,21 +955,34 @@ private static AccountProperties CreateDatabaseAccount( { // Some pre-existing tests depend on the account having multiple write locations even on single master setup // Newer tests can correctly define a single master account (single write region) without breaking existing tests - writeLocations = new Collection() - { - { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } } - }; + writeLocations = isExcludeRegionsTest ? + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } } + } : + new Collection() + { + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } } + } ; } AccountProperties databaseAccount = new AccountProperties() { EnableMultipleWriteLocations = useMultipleWriteLocations, - ReadLocationsInternal = new Collection() - { - { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, - { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, - { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, - }, + ReadLocationsInternal = isExcludeRegionsTest ? + new Collection() + { + { new AccountRegion() { Name = "default", Endpoint = LocationCacheTests.DefaultEndpoint.ToString() } }, + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, + } : + new Collection() + { + { new AccountRegion() { Name = "location1", Endpoint = LocationCacheTests.Location1Endpoint.ToString() } }, + { new AccountRegion() { Name = "location2", Endpoint = LocationCacheTests.Location2Endpoint.ToString() } }, + { new AccountRegion() { Name = "location4", Endpoint = LocationCacheTests.Location4Endpoint.ToString() } }, + }, WriteLocationsInternal = writeLocations }; @@ -810,11 +995,13 @@ private GlobalEndpointManager Initialize( bool isPreferredLocationsListEmpty, bool enforceSingleMasterSingleWriteLocation = false, // Some tests depend on the Initialize to create an account with multiple write locations, even when not multi master ReadOnlyCollection preferedRegionListOverride = null, - bool enablePartitionLevelFailover = false) + bool enablePartitionLevelFailover = false, + bool isExcludeRegionsTest = false) { this.databaseAccount = LocationCacheTests.CreateDatabaseAccount( useMultipleWriteLocations, - enforceSingleMasterSingleWriteLocation); + enforceSingleMasterSingleWriteLocation, + isExcludeRegionsTest); if (isPreferredLocationsListEmpty) { @@ -823,7 +1010,7 @@ private GlobalEndpointManager Initialize( else { // Allow for override at the test method level if needed - this.preferredLocations = preferedRegionListOverride != null ? preferedRegionListOverride : new List() + this.preferredLocations = preferedRegionListOverride ?? new List() { "location1", "location2", @@ -841,8 +1028,8 @@ private GlobalEndpointManager Initialize( this.cache.OnDatabaseAccountRead(this.databaseAccount); this.mockedClient = new Mock(); - mockedClient.Setup(owner => owner.ServiceEndpoint).Returns(LocationCacheTests.DefaultEndpoint); - mockedClient.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny(), It.IsAny())).ReturnsAsync(this.databaseAccount); + this.mockedClient.Setup(owner => owner.ServiceEndpoint).Returns(LocationCacheTests.DefaultEndpoint); + this.mockedClient.Setup(owner => owner.GetDatabaseAccountInternalAsync(It.IsAny(), It.IsAny())).ReturnsAsync(this.databaseAccount); ConnectionPolicy connectionPolicy = new ConnectionPolicy() { @@ -857,14 +1044,9 @@ private GlobalEndpointManager Initialize( GlobalEndpointManager endpointManager = new GlobalEndpointManager(this.mockedClient.Object, connectionPolicy); - if (enablePartitionLevelFailover) - { - this.partitionKeyRangeLocationCache = new GlobalPartitionEndpointManagerCore(endpointManager); - } - else - { - this.partitionKeyRangeLocationCache = GlobalPartitionEndpointManagerNoOp.Instance; - } + this.partitionKeyRangeLocationCache = enablePartitionLevelFailover + ? new GlobalPartitionEndpointManagerCore(endpointManager) + : GlobalPartitionEndpointManagerNoOp.Instance; return endpointManager; } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj index e1dbbe8030..cae7b1fa22 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Microsoft.Azure.Cosmos.Tests.csproj @@ -270,6 +270,9 @@ Always + + Always + PreserveNewest diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs index a075d439f6..05cbfc8384 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerTests.cs @@ -106,9 +106,13 @@ public async Task TestWriteForbiddenScenarioAsync() } } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list provided, if the first + /// region is unavailable for write, then the write should eventually get retried to the next preferred region. + /// [TestMethod] [Timeout(10000)] - public async Task TestServiceUnavailableExceptionScenarioAsync() + public async Task CreateItemAsync_WithPreferredRegionsAndServiceUnavailableForFirstPreferredRegion_ShouldRetryAndSucceedToTheNextPreferredRegion() { GlobalPartitionEndpointManagerTests.SetupAccountAndCacheOperations( out string secondaryRegionNameForUri, @@ -168,16 +172,7 @@ public async Task TestServiceUnavailableExceptionScenarioAsync() Pk = "TestPk" }; - // First create will fail because it is not certain if the payload was sent or not. - try - { - await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); - Assert.Fail("Should throw an exception"); - } - catch (CosmosException ce) when (ce.StatusCode == HttpStatusCode.ServiceUnavailable) - { - Assert.IsNotNull(ce); - } + await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); ItemResponse response = await container.CreateItemAsync(toDoActivity, new Cosmos.PartitionKey(toDoActivity.Pk)); Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); @@ -203,6 +198,65 @@ public async Task TestServiceUnavailableExceptionScenarioAsync() Assert.AreEqual(HttpStatusCode.Created, response.StatusCode); } + /// + /// Test to validate that when the partition level failover is enabled with the preferred regions list is missing, then the client + /// initialization should throw an argument exception and fail. + /// + [TestMethod] + public void CreateItemAsync_WithNoPreferredRegionsAndServiceUnavailable_ShouldThrowArgumentException() + { + GlobalPartitionEndpointManagerTests.SetupAccountAndCacheOperations( + out string secondaryRegionNameForUri, + out string globalEndpoint, + out string secondaryRegionEndpiont, + out string databaseName, + out string containerName, + out ResourceId containerResourceId, + out Mock mockHttpHandler, + out IReadOnlyList primaryRegionPartitionKeyRangeIds, + out TransportAddressUri primaryRegionprimaryReplicaUri); + + Mock mockTransport = new Mock(MockBehavior.Strict); + + MockSetupsHelper.SetupServiceUnavailableException( + mockTransport, + primaryRegionprimaryReplicaUri); + + mockTransport.Setup(x => x.Dispose()); + + // Partition key ranges are the same in both regions so the SDK + // does not need to go the secondary to get the partition key ranges. + // Only the addresses need to be mocked on the secondary + MockSetupsHelper.SetupAddresses( + mockHttpHandler: mockHttpHandler, + partitionKeyRangeId: primaryRegionPartitionKeyRangeIds.First(), + regionEndpoint: secondaryRegionEndpiont, + regionName: secondaryRegionNameForUri, + containerResourceId: containerResourceId, + primaryReplicaUri: out TransportAddressUri secondaryRegionPrimaryReplicaUri); + + MockSetupsHelper.SetupCreateItemResponse( + mockTransport, + secondaryRegionPrimaryReplicaUri); + + CosmosClientOptions cosmosClientOptions = new CosmosClientOptions() + { + EnablePartitionLevelFailover = true, + ConsistencyLevel = Cosmos.ConsistencyLevel.Strong, + HttpClientFactory = () => new HttpClient(new HttpHandlerHelper(mockHttpHandler.Object)), + TransportClientHandlerFactory = (original) => mockTransport.Object, + }; + + ArgumentException exception = Assert.ThrowsException(() => new CosmosClient( + globalEndpoint, + Convert.ToBase64String(Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())), + cosmosClientOptions)); + + Assert.AreEqual( + expected: "ApplicationPreferredRegions is required when EnablePartitionLevelFailover is enabled.", + actual: exception.Message); + } + [TestMethod] [Timeout(10000)] public async Task TestRequestTimeoutExceptionScenarioAsync() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs index 8f1da91c53..06ca0a4c2c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/GlobalPartitionEndpointManagerUnitTests.cs @@ -73,13 +73,15 @@ public void VerifyAllReadRegionsAreVisited(int numOfReadRegions) Mock mockEndpointManager = new Mock(MockBehavior.Strict); GlobalPartitionEndpointManagerCore failoverManager = new GlobalPartitionEndpointManagerCore(mockEndpointManager.Object); - List readRegions = new List(); + List readRegions = new (), writeRegions = new(); for(int i = 0; i < numOfReadRegions; i++) { readRegions.Add(new Uri($"https://localhost:{i}/")); } mockEndpointManager.Setup(x => x.ReadEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); + mockEndpointManager.Setup(x => x.AccountReadEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); + mockEndpointManager.Setup(x => x.WriteEndpoints).Returns(() => new ReadOnlyCollection(readRegions)); // Create a random pk range PartitionKeyRange partitionKeyRange = new PartitionKeyRange() diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs index ebc0e9c61b..5bf63cd3ba 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/PartitionKeyRangeFailoverTests/MockSetupsHelper.cs @@ -279,7 +279,14 @@ internal static HttpResponseMessage CreateAddresses( string regionName, ResourceId containerResourceId) { - string basePhysicalUri = $"rntbd://cdb-ms-prod-{regionName}-fd4.documents.azure.com:14382/apps/9dc0394e-d25f-4c98-baa5-72f1c700bf3e/services/060067c7-a4e9-4465-a412-25cb0104cb58/partitions/2cda760c-f81f-4094-85d0-7bcfb2acc4e6/replicas/"; + int initialPort = 14382; + int[] ports = new int[replicaIds.Count]; + string basePhysicalUri = "rntbd://cdb-ms-prod-{0}-fd4.documents.azure.com:{1}/apps/9dc0394e-d25f-4c98-baa5-72f1c700bf3e/services/060067c7-a4e9-4465-a412-25cb0104cb58/partitions/2cda760c-f81f-4094-85d0-7bcfb2acc4e6/replicas/{2}"; + + for (int i=0; i< replicaIds.Count; i++) + { + ports[i] = initialPort++; + } // Use the partition key range id at the end of each replica id to avoid conflicts when setting up multiple partition key ranges List
addresses = new List
(); @@ -290,7 +297,7 @@ internal static HttpResponseMessage CreateAddresses( { IsPrimary = i == 0, PartitionKeyRangeId = partitionKeyRangeId, - PhysicalUri = basePhysicalUri + repliaId, + PhysicalUri = string.Format(basePhysicalUri, regionName, ports[i], repliaId), Protocol = "rntbd", PartitionIndex = "7718513@164605136" }); diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs index 9076506e64..824232c412 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/OptimisticDirectExecutionQueryBaselineTests.cs @@ -144,7 +144,7 @@ public void NegativeOptimisticDirectExecutionOutput() // This test confirms that TestInjection.EnableOptimisticDirectExection is set to false from default. // Check test "TestPipelineForDistributedQueryAsync" to understand why this is done [TestMethod] - public async Task TestDefaultQueryRequestOptionsSettings() + public void TestDefaultQueryRequestOptionsSettings() { QueryRequestOptions requestOptions = new QueryRequestOptions(); bool odeExpectedValue = @@ -644,7 +644,7 @@ internal static TryCatch TryGetPartitionedQueryEx return tryGetQueryPlan; } - private static async Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) + private static Task GetOdePipelineAsync(OptimisticDirectExecutionTestInput input, DocumentContainer documentContainer, QueryRequestOptions queryRequestOptions) { (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext(input, queryRequestOptions); @@ -655,7 +655,7 @@ private static async Task GetOdePipelineAsync(OptimisticDir NoOpTrace.Singleton); Assert.IsNotNull(queryPipelineStage); - return queryPipelineStage; + return Task.FromResult(queryPipelineStage); } private static async Task CreateDocumentContainerAsync( @@ -801,7 +801,6 @@ public override OptimisticDirectExecutionTestOutput ExecuteTest(OptimisticDirect partitionedQueryExecutionInfo: null, executionEnvironment: null, returnResultsInDeterministicOrder: null, - forcePassthrough: false, enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, testInjections: queryRequestOptions.TestSettings); @@ -913,6 +912,7 @@ public MergeTestUtil(bool isFailedFallbackPipelineTest) this.IsFailedFallbackPipelineTest = isFailedFallbackPipelineTest; } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public async Task ShouldReturnFailure() { this.MoveNextCounter++; @@ -940,6 +940,7 @@ public async Task ShouldReturnFailure() return null; } +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously } } @@ -1094,7 +1095,7 @@ public override Task> TryGetOverlappingRangesAs throw new NotImplementedException(); } - public override async Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) + public override Task> TryGetPartitionedQueryExecutionInfoAsync(SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) { CosmosSerializerCore serializerCore = new(); using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); @@ -1102,7 +1103,7 @@ public override async Task> TryGetPartit TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; - return TryCatch.FromResult(partitionedQueryExecutionInfo); + return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs index 0f8f6f2be7..b02f19374a 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Query/Pipeline/FullPipelineTests.cs @@ -7,19 +7,27 @@ namespace Microsoft.Azure.Cosmos.Tests.Query.Pipeline using System; using System.Collections.Generic; using System.Collections.ObjectModel; + using System.IO; using System.Linq; + using System.Threading; using System.Threading.Tasks; + using Microsoft.Azure.Cosmos.ChangeFeed.Pagination; using Microsoft.Azure.Cosmos.CosmosElements; using Microsoft.Azure.Cosmos.Pagination; + using Microsoft.Azure.Cosmos.Query; using Microsoft.Azure.Cosmos.Query.Core; + using Microsoft.Azure.Cosmos.Query.Core.ExecutionContext; using Microsoft.Azure.Cosmos.Query.Core.Monads; using Microsoft.Azure.Cosmos.Query.Core.Pipeline; using Microsoft.Azure.Cosmos.Query.Core.Pipeline.Pagination; + using Microsoft.Azure.Cosmos.Query.Core.QueryClient; using Microsoft.Azure.Cosmos.Query.Core.QueryPlan; + using Microsoft.Azure.Cosmos.ReadFeed.Pagination; using Microsoft.Azure.Cosmos.Tests.Pagination; using Microsoft.Azure.Cosmos.Tracing; using Microsoft.Azure.Documents; using Microsoft.VisualStudio.TestTools.UnitTesting; + using Moq; using Newtonsoft.Json; [TestClass] @@ -46,7 +54,7 @@ public async Task TestMerge() MergeTestUtil mergeTest = new MergeTestUtil(); mergeTest.DocumentContainer = await CreateDocumentContainerAsync( documents: documents, - numPartitions: 2, + numSplits: 2, failureConfigs: new FlakyDocumentContainer.FailureConfigs( inject429s: false, injectEmptyPages: false, @@ -249,6 +257,159 @@ public async Task Tracing() Assert.AreEqual(numTraces, rootTrace.Children.Count); } + [TestMethod] + public async Task OffsetLimitPageSize() + { + List documents = new List(); + for (int i = 0; i < 1100; i++) + { + documents.Add(CosmosObject.Parse($"{{\"pk\" : {i} }}")); + } + + MockInMemoryContainer mockInMemoryContainer = new MockInMemoryContainer(new InMemoryContainer(partitionKeyDefinition)); + DocumentContainer documentContainer = await CreateDocumentContainerAsync(documents, mockInMemoryContainer, numSplits: 4); + + // OFFSET/LIMIT with ORDER BY + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 500", expectedPageSize: 315, expectedResults: 500, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10000 LIMIT 5000", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 10 LIMIT 100", expectedPageSize: 70, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 0 LIMIT 100", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c ORDER BY c.pk OFFSET 100 LIMIT 0", expectedPageSize: 65, expectedResults: 0, mockInMemoryContainer, documentContainer); + + // OFFSET/LIMIT without ORDER BY + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 10 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 0 LIMIT 100", expectedPageSize: 1000, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT c.pk FROM c OFFSET 100 LIMIT 0", expectedPageSize: 1000, expectedResults: 0, mockInMemoryContainer, documentContainer); + + // TOP with ORDER BY + await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c ORDER BY c.pk", expectedPageSize: 5, expectedResults: 5, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 100 c.pk FROM c ORDER BY c.pk", expectedPageSize: 65, expectedResults: 100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c ORDER BY c.pk", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + + // TOP without ORDER BY + await this.TestPageSizeAsync("SELECT TOP 5 c.pk FROM c", expectedPageSize: 1000, expectedResults: 5, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 5000 c.pk FROM c", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + await this.TestPageSizeAsync("SELECT TOP 15000 c.pk FROM c", expectedPageSize: 1000, expectedResults: 1100, mockInMemoryContainer, documentContainer); + } + + private async Task TestPageSizeAsync(string query, int expectedPageSize, int expectedResults, MockInMemoryContainer inMemoryContainer, DocumentContainer documentContainer) + { + (CosmosQueryExecutionContextFactory.InputParameters inputParameters, CosmosQueryContextCore cosmosQueryContextCore) = CreateInputParamsAndQueryContext( + query, + partitionKeyDefinition, + null, + new QueryRequestOptions()); + + IQueryPipelineStage queryPipelineStage = CosmosQueryExecutionContextFactory.Create( + documentContainer, + cosmosQueryContextCore, + inputParameters, + NoOpTrace.Singleton); + + List elements = new List(); + while (await queryPipelineStage.MoveNextAsync(NoOpTrace.Singleton)) + { + TryCatch tryGetQueryPage = queryPipelineStage.Current; + tryGetQueryPage.ThrowIfFailed(); + + elements.AddRange(tryGetQueryPage.Result.Documents); + } + + Assert.AreEqual(expected: expectedPageSize, actual: inMemoryContainer.PageSizeSpecified); + Assert.AreEqual(expected: expectedResults, actual: elements.Count); + } + + private static Tuple CreateInputParamsAndQueryContext( + string query, + PartitionKeyDefinition partitionKeyDefinition, + Cosmos.PartitionKey? partitionKeyValue, + QueryRequestOptions queryRequestOptions) + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(new SqlQuerySpec(query), Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + CosmosQueryExecutionContextFactory.InputParameters inputParameters = new CosmosQueryExecutionContextFactory.InputParameters( + sqlQuerySpec: new SqlQuerySpec(query), + initialUserContinuationToken: null, + initialFeedRange: null, + maxConcurrency: queryRequestOptions.MaxConcurrency, + maxItemCount: queryRequestOptions.MaxItemCount, + maxBufferedItemCount: queryRequestOptions.MaxBufferedItemCount, + partitionKey: partitionKeyValue, + properties: new Dictionary() { { "x-ms-query-partitionkey-definition", partitionKeyDefinition } }, + partitionedQueryExecutionInfo: null, + executionEnvironment: null, + returnResultsInDeterministicOrder: null, + enableOptimisticDirectExecution: queryRequestOptions.EnableOptimisticDirectExecution, + testInjections: queryRequestOptions.TestSettings); + + string databaseId = "db1234"; + string resourceLink = $"dbs/{databaseId}/colls"; + + const string suffix = "-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF"; + + List partitionKeyRanges = new List + { + new PartitionKeyRange() { MinInclusive = Documents.Routing.PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey, MaxExclusive = "1F" + suffix }, + new PartitionKeyRange() { MinInclusive = "1F" + suffix, MaxExclusive = "3F" + suffix }, + new PartitionKeyRange() { MinInclusive = "3F" + suffix, MaxExclusive = "5F" + suffix }, + new PartitionKeyRange() { MinInclusive = "5F" + suffix, MaxExclusive = "7F" + suffix }, + new PartitionKeyRange() { MinInclusive = "7F" + suffix, MaxExclusive = "9F" + suffix }, + new PartitionKeyRange() { MinInclusive = "9F" + suffix, MaxExclusive = "BF" + suffix }, + new PartitionKeyRange() { MinInclusive = "BF" + suffix, MaxExclusive = "DF" + suffix }, + new PartitionKeyRange() { MinInclusive = "DF" + suffix, MaxExclusive = Documents.Routing.PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey }, + }; + + Mock mockClient = new Mock(); + + mockClient.Setup(x => x.GetTargetPartitionKeyRangesAsync( + It.IsAny(), + It.IsAny(), + It.IsAny>>(), + It.IsAny(), + It.IsAny())) + .Returns((string resourceLink, string collectionResourceId, IReadOnlyList> providedRanges, bool forceRefresh, ITrace trace) => Task.FromResult(partitionKeyRanges)); + + mockClient.Setup(x => x.TryGetPartitionedQueryExecutionInfoAsync( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns((SqlQuerySpec sqlQuerySpec, ResourceType resourceType, PartitionKeyDefinition partitionKeyDefinition, bool requireFormattableOrderByQuery, bool isContinuationExpected, bool allowNonValueAggregateQuery, bool hasLogicalPartitionKey, bool allowDCount, bool useSystemPrefix, Cosmos.GeospatialType geospatialType, CancellationToken cancellationToken) => + { + CosmosSerializerCore serializerCore = new(); + using StreamReader streamReader = new(serializerCore.ToStreamSqlQuerySpec(sqlQuerySpec, Documents.ResourceType.Document)); + string sqlQuerySpecJsonString = streamReader.ReadToEnd(); + + TryCatch queryPlan = OptimisticDirectExecutionQueryBaselineTests.TryGetPartitionedQueryExecutionInfo(sqlQuerySpecJsonString, partitionKeyDefinition); + PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = queryPlan.Succeeded ? queryPlan.Result : throw queryPlan.Exception; + return Task.FromResult(TryCatch.FromResult(partitionedQueryExecutionInfo)); + } + ); + + CosmosQueryContextCore cosmosQueryContextCore = new CosmosQueryContextCore( + client: mockClient.Object, + resourceTypeEnum: Documents.ResourceType.Document, + operationType: Documents.OperationType.Query, + resourceType: typeof(QueryResponseCore), + resourceLink: resourceLink, + isContinuationExpected: true, + allowNonValueAggregateQuery: true, + useSystemPrefix: false, + correlatedActivityId: Guid.NewGuid()); + + return Tuple.Create(inputParameters, cosmosQueryContextCore); + } + internal static async Task> ExecuteQueryAsync( string query, IReadOnlyList documents, @@ -329,13 +490,13 @@ private static async Task> DrainWithStateAsync(string query, return elements; } - internal static Task CreateDocumentContainerAsync( + internal static Task CreateDocumentContainerAsync( IReadOnlyList documents, - int numPartitions = 3, + int numSplits = 3, FlakyDocumentContainer.FailureConfigs failureConfigs = null) { IMonadicDocumentContainer monadicDocumentContainer = CreateMonadicDocumentContainerAsync(failureConfigs); - return CreateDocumentContainerAsync(documents, monadicDocumentContainer, numPartitions); + return CreateDocumentContainerAsync(documents, monadicDocumentContainer, numSplits); } internal static IMonadicDocumentContainer CreateMonadicDocumentContainerAsync(FlakyDocumentContainer.FailureConfigs failureConfigs) @@ -349,14 +510,14 @@ internal static IMonadicDocumentContainer CreateMonadicDocumentContainerAsync(Fl return monadicDocumentContainer; } - internal static async Task CreateDocumentContainerAsync( + internal static async Task CreateDocumentContainerAsync( IReadOnlyList documents, IMonadicDocumentContainer monadicDocumentContainer, - int numPartitions) + int numSplits) { DocumentContainer documentContainer = new DocumentContainer(monadicDocumentContainer); - for (int i = 0; i < numPartitions; i++) + for (int i = 0; i < numSplits; i++) { IReadOnlyList ranges = await documentContainer.GetFeedRangesAsync( trace: NoOpTrace.Singleton, @@ -461,5 +622,79 @@ public async Task ShouldReturnFailure() } } } + + private class MockInMemoryContainer : IMonadicDocumentContainer + { + public int? PageSizeSpecified { get; private set; } + public IMonadicDocumentContainer MonadicDocumentContainer { get; } + + public MockInMemoryContainer(IMonadicDocumentContainer documentContainer) + { + this.MonadicDocumentContainer = documentContainer; + this.PageSizeSpecified = null; + } + + public void Reset() + { + this.PageSizeSpecified = null; + } + + public Task> MonadicChangeFeedAsync(FeedRangeState feedRangeState, ChangeFeedPaginationOptions changeFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicChangeFeedAsync(feedRangeState, changeFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicCreateItemAsync(CosmosObject payload, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicCreateItemAsync(payload, cancellationToken); + } + + public Task>> MonadicGetChildRangeAsync(FeedRangeInternal feedRange, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetChildRangeAsync(feedRange, trace, cancellationToken); + } + + public Task>> MonadicGetFeedRangesAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetFeedRangesAsync(trace, cancellationToken); + } + + public Task> MonadicGetResourceIdentifierAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicGetResourceIdentifierAsync(trace, cancellationToken); + } + + public Task MonadicMergeAsync(FeedRangeInternal feedRange1, FeedRangeInternal feedRange2, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicMergeAsync(feedRange1, feedRange2, cancellationToken); + } + + public Task> MonadicQueryAsync(SqlQuerySpec sqlQuerySpec, FeedRangeState feedRangeState, QueryPaginationOptions queryPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + this.PageSizeSpecified = queryPaginationOptions.PageSizeLimit; + + return this.MonadicDocumentContainer.MonadicQueryAsync(sqlQuerySpec, feedRangeState, queryPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicReadFeedAsync(FeedRangeState feedRangeState, ReadFeedPaginationOptions readFeedPaginationOptions, ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicReadFeedAsync(feedRangeState, readFeedPaginationOptions, trace, cancellationToken); + } + + public Task> MonadicReadItemAsync(CosmosElement partitionKey, string identifier, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicReadItemAsync(partitionKey, identifier, cancellationToken); + } + + public Task MonadicRefreshProviderAsync(ITrace trace, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicRefreshProviderAsync(trace, cancellationToken); + } + + public Task MonadicSplitAsync(FeedRangeInternal feedRange, CancellationToken cancellationToken) + { + return this.MonadicDocumentContainer.MonadicSplitAsync(feedRange, cancellationToken); + } + } } } diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs index d58ab3db5b..944cb6de8c 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/Routing/AsyncCacheNonBlockingTests.cs @@ -394,15 +394,15 @@ await asyncCache.GetAsync( } /// - /// Test to validate that when RefreshAsync() is invoked for a valid existing key, the + /// Test to validate that when Refresh() is invoked for a valid existing key, the /// cache refreshes the key successfully and the new value is updated in the cache. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenRefreshRequestedForAnExistingKey_ShouldRefreshTheCache() + public async Task Refresh_WhenRefreshRequestedForAnExistingKey_ShouldRefreshTheCache() { // Arrange. - AsyncCacheNonBlocking asyncCache = new (); + AsyncCacheNonBlocking asyncCache = new(); // Act and Assert. string result = await asyncCache.GetAsync( @@ -412,10 +412,14 @@ public async Task RefreshAsync_WhenRefreshRequestedForAnExistingKey_ShouldRefres Assert.AreEqual("value1", result); - await asyncCache.RefreshAsync( + asyncCache.Refresh( "key", (_) => Task.FromResult("value2")); + // Add some delay for the background refresh task to complete. + await Task.Delay( + millisecondsDelay: 50); + result = await asyncCache.GetAsync( "key", (_) => throw new Exception("Should not refresh."), @@ -425,15 +429,15 @@ await asyncCache.RefreshAsync( } /// - /// Test to validate that when a DocumentClientException is thrown during RefreshAsync() operation, + /// Test to validate that when a DocumentClientException is thrown during Refresh() operation, /// then the cache removes the key for which a refresh was requested. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenThrowsDocumentClientException_ShouldRemoveKeyFromTheCache() + public async Task Refresh_WhenThrowsDocumentClientException_ShouldRemoveKeyFromTheCache() { // Arrange. - AsyncCacheNonBlocking asyncCache = new (); + AsyncCacheNonBlocking asyncCache = new(); // Act and Assert. string result = await asyncCache.GetAsync( @@ -453,23 +457,20 @@ public async Task RefreshAsync_WhenThrowsDocumentClientException_ShouldRemoveKey // and still return the old cached value. Assert.AreEqual("value1", result); - NotFoundException notFoundException = new ( + NotFoundException notFoundException = new( message: "Item was deleted."); - try - { - await asyncCache.RefreshAsync( - "key", - async (_) => - { - await Task.Delay(TimeSpan.FromMilliseconds(5)); - throw notFoundException; - }); - Assert.Fail("Should throw a NotFoundException"); - } - catch (NotFoundException exception) - { - Assert.AreEqual(notFoundException, exception); - } + + asyncCache.Refresh( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw notFoundException; + }); + + // Add some delay for the background refresh task to complete. + await Task.Delay( + millisecondsDelay: 50); // Because the key was deleted from the cache, the func delegate should get invoked at // this point and update the value to value2. @@ -482,12 +483,12 @@ await asyncCache.RefreshAsync( } /// - /// Test to validate that when some other Exception is thrown during RefreshAsync() operation, + /// Test to validate that when some other Exception is thrown during Refresh() operation, /// then the cache does not remove the key for which the refresh was originally requested. /// [TestMethod] [Owner("dkunda")] - public async Task RefreshAsync_WhenThrowsOtherException_ShouldNotRemoveKeyFromTheCache() + public async Task Refresh_WhenThrowsOtherException_ShouldNotRemoveKeyFromTheCache() { // Arrange. AsyncCacheNonBlocking asyncCache = new(); @@ -512,21 +513,14 @@ public async Task RefreshAsync_WhenThrowsOtherException_ShouldNotRemoveKeyFromTh Exception exception = new( message: "Timeout exception."); - try - { - await asyncCache.RefreshAsync( - "key", - async (_) => - { - await Task.Delay(TimeSpan.FromMilliseconds(5)); - throw exception; - }); - Assert.Fail("Should throw a NotFoundException"); - } - catch (Exception ex) - { - Assert.AreEqual(ex, exception); - } + + asyncCache.Refresh( + "key", + async (_) => + { + await Task.Delay(TimeSpan.FromMilliseconds(5)); + throw exception; + }); // Because the key should not get deleted from the cache, the func delegate should not get invoked at // this point. diff --git a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs index 5ff15ed9a3..f9cb21805f 100644 --- a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs +++ b/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/ServicePointAccessorTests.cs @@ -11,7 +11,7 @@ namespace Microsoft.Azure.Cosmos.Tests [TestClass] public class ServicePointAccessorTests { - private static Uri uri = new Uri("https://localhost"); + private static readonly Uri uri = new Uri("https://localhost"); [TestMethod] public void ServicePointAccessor_SetConnectionLimit() @@ -20,7 +20,9 @@ public void ServicePointAccessor_SetConnectionLimit() ServicePointAccessor accessor = ServicePointAccessor.FindServicePoint(ServicePointAccessorTests.uri); Assert.IsNotNull(accessor); accessor.ConnectionLimit = limit; +#pragma warning disable SYSLIB0014 // Type or member is obsolete ServicePoint servicePoint = ServicePointManager.FindServicePoint(ServicePointAccessorTests.uri); +#pragma warning restore SYSLIB0014 // Type or member is obsolete Assert.AreEqual(limit, servicePoint.ConnectionLimit); } @@ -29,7 +31,9 @@ public void ServicePointAccessor_DisableNagle() { ServicePointAccessor accessor = ServicePointAccessor.FindServicePoint(ServicePointAccessorTests.uri); Assert.IsNotNull(accessor); +#pragma warning disable SYSLIB0014 // Type or member is obsolete ServicePoint servicePoint = ServicePointManager.FindServicePoint(ServicePointAccessorTests.uri); +#pragma warning restore SYSLIB0014 // Type or member is obsolete Assert.IsFalse(servicePoint.UseNagleAlgorithm); } } diff --git a/README.md b/README.md index f1dcffa7b9..861235223a 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,8 @@ using (FeedIterator feedIterator = container.GetItemQueryIterator [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-17 +### [3.37.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0-preview) - 2023-11-17 +### [3.37.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.37.0) - 2023-11-17 + +#### Fixed +- [4100](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4100) Query : Fixes querying conflicts (#4100) +- [4125](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4125) Item Operations: Fixes JsonSerialization exception when MissingMemberHandling = Error on Json default settings when NotFound on Item operations (#4125) + +#### Added +- [4180](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4180) Upgrade Resiliency: Adds Code to Enable Advanced Replica Selection Feature for Preview and GA (#4180) +- [4128](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4128) Routing: Adds ExcludeRegions Feature to RequestOptions (#4128) + +### [3.36.0](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0) - 2023-10-24 #### Fixed - [4039](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4039) GatewayAddressCache: Fixes Unobserved Exception During Background Address Refresh (#4039) @@ -30,7 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > Note: Refer this [3983](https://github.com/Azure/azure-cosmos-dotnet-v3/issues/3983) for API signature and default values. - [4119](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4119) TriggerOperation: Adds Upsert Operation Support(#4119) -### [3.356.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0-preview) - 2023-10-17 +### [3.36.0-preview](https://www.nuget.org/packages/Microsoft.Azure.Cosmos/3.36.0-preview) - 2023-10-24 #### Added - [4056](https://github.com/Azure/azure-cosmos-dotnet-v3/pull/4056) Client Telemetry: Adds new public APIs (#4056). WARNING: This is breaking change for preview SDK diff --git a/docs/PerPartitionAutomaticFailoverDesign.md b/docs/PerPartitionAutomaticFailoverDesign.md new file mode 100644 index 0000000000..fa1425c5d3 --- /dev/null +++ b/docs/PerPartitionAutomaticFailoverDesign.md @@ -0,0 +1,28 @@ +# Working Principles for Per Partition Automatic Failover + +## Table of Contents + +* [Scope.](#scope) +* [Background.](#background) +* [How Does the SDK know Which Region to Fail Over.](#how-does-the-sdk-know-which-region-to-fail-over) +* [References.](#references) + +## Scope + +The scope of the per partition automatic failover design document is applicable for the Cosmos .NET SDK configured only for `Direct` mode at the moment. + +## Background + +Today, the partition level failovers are applicable for multi master write acounts, for a simple reason. If one of the write region fails with a write forbidden 403 exception, then the SDK has the knowledge (by looking up the `ApplicationPreferredRegions`) of the other regions to failover. With the per partition automatic failover, if a partition is in quorum loss, then the backend automatically marks another region as the write region, based on the account configuration. Therefore, any retry for the write requests, to the next preferred region should be successful. + +This idea extends the SDK's retry logic to retry the write requests for single master write accounts, for any service unavailable (status codes 503) errors. + +## How Does the SDK know Which Region to Fail Over + +Right now, the .NET SDK depends upon the `GlobalPartitionEndpointManagerCore` to resolve the endpoints. There is a method `TryMarkEndpointUnavailableForPartitionKeyRange()` within the class, that is responsible to add the override by iterating over the next read regions. This is how the .NET SDK knows which region to fail over. + +## References + +- [SDK not retrying with next region in case address resolution call to Gateway call fails with 503.](https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2475521/) +- [First client write request after failover is failing with 503(21005)](https://msdata.visualstudio.com/CosmosDB/_workitems/edit/2492475/) +- [PPAF Testing in Test, Staging and Prod.](https://microsoft.sharepoint.com/:w:/r/teams/DocumentDB/_layouts/15/doc2.aspx?sourcedoc=%7B7587D267-212F-47BE-AAD6-18FC53482B68%7D&file=PPAF%20Testing%20in%20Test%2C%20Staging%20and%20Prod.docx&action=default&mobileredirect=true) \ No newline at end of file diff --git a/docs/versioning.md b/docs/versioning.md new file mode 100644 index 0000000000..778b3d2504 --- /dev/null +++ b/docs/versioning.md @@ -0,0 +1,50 @@ +# Versioning + +The Azure Cosmos DB SDK ships two [Nuget package](https://www.nuget.org/packages/Microsoft.Azure.Cosmos) versions: + +* GA SDK: Versioned with `3.X.Y`, it contains APIs and features that are considered General Availability +* Preview SDK: Versioned with `3.(X + 1).0-preview.Y`, it contains APIs and features that are in Preview. These APIs or features might be service features that are in Preview (such as a new Cosmos DB Service feature or operation) or SDK client specific features that are unrelated to a service feature (such as improvements in connection handling). + +> :information_source: General Availability of an API or feature present in a Preview SDK is not guaranteed on the next GA SDK release following the Preview SDK release when it was introduced. Each Preview API can have an independent GA cycle that can be dependent on the Azure Cosmos DB Service. + +## Major releases + +Major releases are defined by: + +* Significant breaking changes to the API surface of the SDK. +* Significant breaking changes to dependencies + +> :information_source: No new major release is currently planned. + +## Minor releases + +Minor releases are defined by: + +* Changes in the public API surface of the SDK, such as new features, or GAing APIs that were in preview +* Changes in the version of one of the dependencies + +In these cases, the **GA SDK** should **increase the minor version** and **Preview SDK** should **increase the minor version to be one more than GA SDK**. + +For example, if `3.10.0` is being released for **GA SDK**, then `3.11.0-preview.0` should be released for **Preview SDK**. + +## Patch releases + +Patch releases are defined by: + +* No Public API changes +* Includes a subset of the bug fixes reported after the last major release + +In these cases, the **GA SDK** should **increase the patch version** and **Preview SDK** should **increase the preview suffix version**. + +For example, if `3.10.0` is being patched, for **GA SDK** we would release `3.10.1` and for **Preview SDK** we would release `3.11.0-preview.1`. + +If `3.10.1` is being patched, for **GA SDK** we would release `3.10.2` and for **Preview SDK** we would release `3.11.0-preview.2`. + +## Complete full example + +| GA | Preview | +|----------|-----------| +| 3.10.0 | 3.11.0-preview.0 | +| 3.10.1 | 3.11.0-preview.1 | +| 3.10.2 | 3.11.0-preview.2 | +| 3.11.0 | 3.12.0-preview.0 |