@azure/cosmos 4.6.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/ClientContext.js +2 -2
- package/dist/browser/ClientContext.js.map +1 -1
- package/dist/browser/CosmosClient.d.ts.map +1 -1
- package/dist/browser/CosmosClient.js +3 -0
- package/dist/browser/CosmosClient.js.map +1 -1
- package/dist/browser/common/constants.js +1 -1
- package/dist/browser/common/constants.js.map +1 -1
- package/dist/browser/documents/ConnectionPolicy.d.ts +6 -3
- package/dist/browser/documents/ConnectionPolicy.d.ts.map +1 -1
- package/dist/browser/documents/ConnectionPolicy.js +1 -1
- package/dist/browser/documents/ConnectionPolicy.js.map +1 -1
- package/dist/browser/globalEndpointManager.d.ts +0 -6
- package/dist/browser/globalEndpointManager.d.ts.map +1 -1
- package/dist/browser/globalEndpointManager.js +51 -14
- package/dist/browser/globalEndpointManager.js.map +1 -1
- package/dist/browser/globalPartitionEndpointManager.d.ts +1 -1
- package/dist/browser/globalPartitionEndpointManager.d.ts.map +1 -1
- package/dist/browser/globalPartitionEndpointManager.js +36 -11
- package/dist/browser/globalPartitionEndpointManager.js.map +1 -1
- package/dist/browser/request/RequestHandler.js +2 -2
- package/dist/browser/request/RequestHandler.js.map +1 -1
- package/dist/browser/retry/timeoutFailoverRetryPolicy.js +1 -1
- package/dist/browser/retry/timeoutFailoverRetryPolicy.js.map +1 -1
- package/dist/commonjs/ClientContext.js +2 -2
- package/dist/commonjs/ClientContext.js.map +1 -1
- package/dist/commonjs/CosmosClient.d.ts.map +1 -1
- package/dist/commonjs/CosmosClient.js +3 -0
- package/dist/commonjs/CosmosClient.js.map +1 -1
- package/dist/commonjs/common/constants.js +1 -1
- package/dist/commonjs/common/constants.js.map +1 -1
- package/dist/commonjs/documents/ConnectionPolicy.d.ts +6 -3
- package/dist/commonjs/documents/ConnectionPolicy.d.ts.map +1 -1
- package/dist/commonjs/documents/ConnectionPolicy.js +1 -1
- package/dist/commonjs/documents/ConnectionPolicy.js.map +1 -1
- package/dist/commonjs/globalEndpointManager.d.ts +0 -6
- package/dist/commonjs/globalEndpointManager.d.ts.map +1 -1
- package/dist/commonjs/globalEndpointManager.js +51 -14
- package/dist/commonjs/globalEndpointManager.js.map +1 -1
- package/dist/commonjs/globalPartitionEndpointManager.d.ts +1 -1
- package/dist/commonjs/globalPartitionEndpointManager.d.ts.map +1 -1
- package/dist/commonjs/globalPartitionEndpointManager.js +36 -11
- package/dist/commonjs/globalPartitionEndpointManager.js.map +1 -1
- package/dist/commonjs/request/RequestHandler.js +2 -2
- package/dist/commonjs/request/RequestHandler.js.map +1 -1
- package/dist/commonjs/retry/timeoutFailoverRetryPolicy.js +1 -1
- package/dist/commonjs/retry/timeoutFailoverRetryPolicy.js.map +1 -1
- package/dist/commonjs/tsdoc-metadata.json +1 -1
- package/dist/esm/ClientContext.js +2 -2
- package/dist/esm/ClientContext.js.map +1 -1
- package/dist/esm/CosmosClient.d.ts.map +1 -1
- package/dist/esm/CosmosClient.js +3 -0
- package/dist/esm/CosmosClient.js.map +1 -1
- package/dist/esm/common/constants.js +1 -1
- package/dist/esm/common/constants.js.map +1 -1
- package/dist/esm/documents/ConnectionPolicy.d.ts +6 -3
- package/dist/esm/documents/ConnectionPolicy.d.ts.map +1 -1
- package/dist/esm/documents/ConnectionPolicy.js +1 -1
- package/dist/esm/documents/ConnectionPolicy.js.map +1 -1
- package/dist/esm/globalEndpointManager.d.ts +0 -6
- package/dist/esm/globalEndpointManager.d.ts.map +1 -1
- package/dist/esm/globalEndpointManager.js +51 -14
- package/dist/esm/globalEndpointManager.js.map +1 -1
- package/dist/esm/globalPartitionEndpointManager.d.ts +1 -1
- package/dist/esm/globalPartitionEndpointManager.d.ts.map +1 -1
- package/dist/esm/globalPartitionEndpointManager.js +36 -11
- package/dist/esm/globalPartitionEndpointManager.js.map +1 -1
- package/dist/esm/request/RequestHandler.js +2 -2
- package/dist/esm/request/RequestHandler.js.map +1 -1
- package/dist/esm/retry/timeoutFailoverRetryPolicy.js +1 -1
- package/dist/esm/retry/timeoutFailoverRetryPolicy.js.map +1 -1
- package/dist/react-native/ClientContext.js +2 -2
- package/dist/react-native/ClientContext.js.map +1 -1
- package/dist/react-native/CosmosClient.d.ts.map +1 -1
- package/dist/react-native/CosmosClient.js +3 -0
- package/dist/react-native/CosmosClient.js.map +1 -1
- package/dist/react-native/common/constants.js +1 -1
- package/dist/react-native/common/constants.js.map +1 -1
- package/dist/react-native/documents/ConnectionPolicy.d.ts +6 -3
- package/dist/react-native/documents/ConnectionPolicy.d.ts.map +1 -1
- package/dist/react-native/documents/ConnectionPolicy.js +1 -1
- package/dist/react-native/documents/ConnectionPolicy.js.map +1 -1
- package/dist/react-native/globalEndpointManager.d.ts +0 -6
- package/dist/react-native/globalEndpointManager.d.ts.map +1 -1
- package/dist/react-native/globalEndpointManager.js +51 -14
- package/dist/react-native/globalEndpointManager.js.map +1 -1
- package/dist/react-native/globalPartitionEndpointManager.d.ts +1 -1
- package/dist/react-native/globalPartitionEndpointManager.d.ts.map +1 -1
- package/dist/react-native/globalPartitionEndpointManager.js +36 -11
- package/dist/react-native/globalPartitionEndpointManager.js.map +1 -1
- package/dist/react-native/request/RequestHandler.js +2 -2
- package/dist/react-native/request/RequestHandler.js.map +1 -1
- package/dist/react-native/retry/timeoutFailoverRetryPolicy.js +1 -1
- package/dist/react-native/retry/timeoutFailoverRetryPolicy.js.map +1 -1
- package/package.json +14 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalEndpointManager.js","sourceRoot":"","sources":["../../src/globalEndpointManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport { OperationType, ResourceType, isReadRequest } from \"./common/index.js\";\nimport type { CosmosClientOptions } from \"./CosmosClientOptions.js\";\nimport type { Location, DatabaseAccount } from \"./documents/index.js\";\nimport type { RequestOptions } from \"./index.js\";\nimport type { ResolveServiceEndpointOptions } from \"./GlobalEndpointManagerOptions.js\";\nimport { Constants } from \"./common/constants.js\";\nimport type { ResourceResponse } from \"./request/index.js\";\nimport { MetadataLookUpType } from \"./CosmosDiagnostics.js\";\nimport type { DiagnosticNodeInternal } from \"./diagnostics/DiagnosticNodeInternal.js\";\nimport { withMetadataDiagnostics } from \"./utils/diagnostics.js\";\nimport { normalizeEndpoint } from \"./utils/checkURL.js\";\nimport { canApplyExcludedLocations } from \"./common/helper.js\";\n\n/**\n * @hidden\n * This internal class implements the logic for endpoint management for geo-replicated database accounts.\n */\nexport class GlobalEndpointManager {\n /**\n * The endpoint used to create the client instance.\n */\n private defaultEndpoint: string;\n /**\n * Flag to enable/disable automatic redirecting of requests based on read/write operations.\n */\n public enableEndpointDiscovery: boolean;\n private isRefreshing: boolean;\n private options: CosmosClientOptions;\n /**\n * List of azure regions to be used as preferred locations for read requests.\n */\n private preferredLocations: string[];\n private writeableLocations: Location[] = [];\n private readableLocations: Location[] = [];\n private unavailableReadableLocations: Location[] = [];\n private unavailableWriteableLocations: Location[] = [];\n private enableMultipleWriteLocations: boolean;\n\n public preferredLocationsCount: number;\n /**\n * Flag to enable/disable the Per Partition Level Failover (PPAF)\n * @internal\n */\n public enablePartitionLevelFailover: boolean;\n /**\n * Flag to enable/disable the Per Partition Level Circuit Breaker (PPCB)\n * @internal\n */\n public enablePartitionLevelCircuitBreaker: boolean;\n\n /**\n * @param options - The document client instance.\n * @internal\n */\n constructor(\n options: CosmosClientOptions,\n private readDatabaseAccount: (\n diagnosticNode: DiagnosticNodeInternal,\n opts: RequestOptions,\n ) => Promise<ResourceResponse<DatabaseAccount>>,\n ) {\n this.options = options;\n this.defaultEndpoint = options.endpoint;\n this.enableEndpointDiscovery = options.connectionPolicy.enableEndpointDiscovery;\n this.isRefreshing = false;\n this.preferredLocations = this.options.connectionPolicy.preferredLocations;\n this.preferredLocationsCount = this.preferredLocations ? this.preferredLocations.length : 0;\n this.enablePartitionLevelFailover = options.connectionPolicy.enablePartitionLevelFailover;\n this.enablePartitionLevelCircuitBreaker =\n options.connectionPolicy.enablePartitionLevelCircuitBreaker ||\n options.connectionPolicy.enablePartitionLevelFailover;\n }\n\n /**\n * Gets the current read endpoint from the endpoint cache.\n */\n public async getReadEndpoint(diagnosticNode: DiagnosticNodeInternal): Promise<string> {\n return this.resolveServiceEndpoint(diagnosticNode, ResourceType.item, OperationType.Read);\n }\n\n /**\n * Gets the current write endpoint from the endpoint cache.\n */\n public async getWriteEndpoint(diagnosticNode: DiagnosticNodeInternal): Promise<string> {\n return this.resolveServiceEndpoint(diagnosticNode, ResourceType.item, OperationType.Replace);\n }\n\n public async getReadEndpoints(): Promise<ReadonlyArray<string>> {\n return this.readableLocations.map((loc) => loc.databaseAccountEndpoint);\n }\n\n public async getWriteEndpoints(): Promise<ReadonlyArray<string>> {\n return this.writeableLocations.map((loc) => loc.databaseAccountEndpoint);\n }\n\n /**\n * Gets the read locations from the endpoint cache.\n */\n public async getReadLocations(): Promise<ReadonlyArray<Location>> {\n return this.readableLocations;\n }\n\n public async markCurrentLocationUnavailableForRead(\n diagnosticNode: DiagnosticNodeInternal,\n endpoint: string,\n ): Promise<void> {\n await this.refreshEndpointList(diagnosticNode);\n const location = this.readableLocations.find((loc) => loc.databaseAccountEndpoint === endpoint);\n if (location) {\n location.unavailable = true;\n location.lastUnavailabilityTimestampInMs = Date.now();\n this.unavailableReadableLocations.push(location);\n }\n }\n\n public async markCurrentLocationUnavailableForWrite(\n diagnosticNode: DiagnosticNodeInternal,\n endpoint: string,\n ): Promise<void> {\n await this.refreshEndpointList(diagnosticNode);\n const location = this.writeableLocations.find(\n (loc) => loc.databaseAccountEndpoint === endpoint,\n );\n if (location) {\n location.unavailable = true;\n location.lastUnavailabilityTimestampInMs = Date.now();\n this.unavailableWriteableLocations.push(location);\n }\n }\n\n public canUseMultipleWriteLocations(\n resourceType?: ResourceType,\n operationType?: OperationType,\n ): boolean {\n let canUse =\n this.options.connectionPolicy.useMultipleWriteLocations && this.enableMultipleWriteLocations;\n\n if (resourceType) {\n canUse =\n canUse &&\n (resourceType === ResourceType.item ||\n (resourceType === ResourceType.sproc && operationType === OperationType.Execute));\n }\n\n return canUse;\n }\n\n private getEffectiveExcludedLocations(\n excludedLocations: string[] = [],\n resourceType: ResourceType,\n ): Set<string> {\n if (!canApplyExcludedLocations(resourceType)) {\n return new Set();\n }\n\n return excludedLocations.length ? new Set(excludedLocations.map(normalizeEndpoint)) : new Set();\n }\n\n private filterExcludedLocations(\n preferredLocations: string[],\n excludedLocations?: Set<string>,\n ): string[] {\n if (!excludedLocations || excludedLocations.size === 0) {\n return preferredLocations;\n }\n const filteredLocations = preferredLocations.filter((location) => {\n return !excludedLocations.has(normalizeEndpoint(location));\n });\n return filteredLocations;\n }\n\n public async resolveServiceEndpoint(\n diagnosticNode: DiagnosticNodeInternal,\n resourceType: ResourceType,\n operationType: OperationType,\n startServiceEndpointIndex: number = 0, // Represents the starting index for selecting servers.\n ): Promise<string> {\n return this.resolveServiceEndpointInternal({\n diagnosticNode: diagnosticNode,\n resourceType: resourceType,\n operationType: operationType,\n startServiceEndpointIndex: startServiceEndpointIndex,\n });\n }\n\n /**\n * @internal\n */\n public async resolveServiceEndpointInternal(\n resolveServiceEndpointOptions: ResolveServiceEndpointOptions,\n ): Promise<string> {\n // Extract all fields from ResolveServiceEndpointOptions\n const {\n diagnosticNode,\n resourceType,\n operationType,\n startServiceEndpointIndex,\n excludedLocations = [],\n } = resolveServiceEndpointOptions;\n\n // If endpoint discovery is disabled, always use the user provided endpoint\n\n if (!this.options.connectionPolicy.enableEndpointDiscovery) {\n diagnosticNode.addData({ readFromCache: true }, \"default_endpoint\");\n diagnosticNode.recordEndpointResolution(this.defaultEndpoint);\n return this.defaultEndpoint;\n }\n\n // If getting the database account, always use the user provided endpoint\n if (resourceType === ResourceType.none) {\n diagnosticNode.addData({ readFromCache: true }, \"none_resource\");\n diagnosticNode.recordEndpointResolution(this.defaultEndpoint);\n return this.defaultEndpoint;\n }\n if (this.readableLocations.length === 0 || this.writeableLocations.length === 0) {\n const resourceResponse = await withMetadataDiagnostics(\n async (metadataNode: DiagnosticNodeInternal) => {\n return this.readDatabaseAccount(metadataNode, {\n urlConnection: this.defaultEndpoint,\n });\n },\n diagnosticNode,\n MetadataLookUpType.DatabaseAccountLookUp,\n );\n\n this.writeableLocations = resourceResponse.resource.writableLocations;\n this.readableLocations = resourceResponse.resource.readableLocations;\n this.enableMultipleWriteLocations = resourceResponse.resource.enableMultipleWritableLocations;\n this.refreshPPAFFeatureFlag(resourceResponse.resource.enablePerPartitionFailover);\n }\n\n const locations = isReadRequest(operationType)\n ? this.readableLocations\n : this.writeableLocations;\n\n const effectiveExcludedLocations = this.getEffectiveExcludedLocations(\n excludedLocations,\n resourceType,\n );\n diagnosticNode.addData(\n { excludedLocations: Array.from(effectiveExcludedLocations) },\n \"excluded_locations\",\n );\n\n // Filter locations based on exclusions\n const availableLocations = this.filterExcludedLocations(\n this.preferredLocations,\n effectiveExcludedLocations,\n );\n\n let location;\n // If we have preferred locations, try each one in order and use the first available one\n if (\n availableLocations &&\n availableLocations.length > 0 &&\n startServiceEndpointIndex < availableLocations.length\n ) {\n this.preferredLocationsCount = availableLocations.length;\n\n for (let i = startServiceEndpointIndex; i < availableLocations.length; i++) {\n const preferredLocation = availableLocations[i];\n location = locations.find(\n (loc) =>\n loc.unavailable !== true &&\n normalizeEndpoint(loc.name) === normalizeEndpoint(preferredLocation),\n );\n if (location) {\n break;\n }\n }\n }\n\n // If no preferred locations or one did not match, just grab the first one that is available\n if (!location) {\n const startIndexValid =\n startServiceEndpointIndex >= 0 && startServiceEndpointIndex < locations.length;\n const locationsToSearch = startIndexValid\n ? locations.slice(startServiceEndpointIndex)\n : locations;\n location = locationsToSearch.find((loc) => {\n return (\n loc.unavailable !== true && !effectiveExcludedLocations.has(normalizeEndpoint(loc.name))\n );\n });\n }\n\n location = location ? location : { name: \"\", databaseAccountEndpoint: this.defaultEndpoint };\n diagnosticNode.recordEndpointResolution(location.databaseAccountEndpoint);\n return location.databaseAccountEndpoint;\n }\n\n /**\n * Refreshes the endpoint list by clearning stale unavailability and then\n * retrieving the writable and readable locations from the geo-replicated database account\n * and then updating the locations cache.\n * We skip the refreshing if enableEndpointDiscovery is set to False\n */\n public async refreshEndpointList(diagnosticNode: DiagnosticNodeInternal): Promise<void> {\n if (!this.isRefreshing && this.enableEndpointDiscovery) {\n this.isRefreshing = true;\n const databaseAccount = await this.getDatabaseAccountFromAnyEndpoint(diagnosticNode);\n if (databaseAccount) {\n this.refreshStaleUnavailableLocations();\n this.refreshEndpoints(databaseAccount);\n }\n this.isRefreshing = false;\n }\n }\n\n private refreshEndpoints(databaseAccount: DatabaseAccount): void {\n const oldWritableLocations = this.writeableLocations;\n const oldReadableLocations = this.readableLocations;\n\n function merge(loc: Location, oldList: Location[]): Location {\n const prev = oldList.find((o) => o.name === loc.name);\n if (prev) {\n loc.unavailable = prev.unavailable;\n loc.lastUnavailabilityTimestampInMs = prev.lastUnavailabilityTimestampInMs;\n }\n return loc;\n }\n\n this.writeableLocations = databaseAccount.writableLocations.map((loc) =>\n merge({ ...loc }, oldWritableLocations),\n );\n this.readableLocations = databaseAccount.readableLocations.map((loc) =>\n merge({ ...loc }, oldReadableLocations),\n );\n }\n\n private refreshStaleUnavailableLocations(): void {\n const now = Date.now();\n this.updateLocation(now, this.unavailableReadableLocations, this.readableLocations);\n this.unavailableReadableLocations = this.cleanUnavailableLocationList(\n now,\n this.unavailableReadableLocations,\n );\n\n this.updateLocation(now, this.unavailableWriteableLocations, this.writeableLocations);\n this.unavailableWriteableLocations = this.cleanUnavailableLocationList(\n now,\n this.unavailableWriteableLocations,\n );\n }\n\n /**\n * update the locationUnavailability to undefined if the location is available again\n * @param now - current time\n * @param unavailableLocations - list of unavailable locations\n * @param allLocations - list of all locations\n */\n private updateLocation(\n now: number,\n unavailableLocations: Location[],\n allLocations: Location[],\n ): void {\n for (const location of unavailableLocations) {\n const unavailableLocation = allLocations.find((loc) => loc.name === location.name);\n if (\n unavailableLocation &&\n now - unavailableLocation.lastUnavailabilityTimestampInMs >\n Constants.LocationUnavailableExpirationTimeInMs\n ) {\n unavailableLocation.unavailable = false;\n }\n }\n }\n\n private cleanUnavailableLocationList(now: number, unavailableLocations: Location[]): Location[] {\n return unavailableLocations.filter((loc) => {\n return (\n now - loc.lastUnavailabilityTimestampInMs < Constants.LocationUnavailableExpirationTimeInMs\n );\n });\n }\n\n /**\n * Gets the database account first by using the default endpoint, and if that doesn't returns\n * use the endpoints for the preferred locations in the order they are specified to get\n * the database account.\n */\n private async getDatabaseAccountFromAnyEndpoint(\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<DatabaseAccount> {\n try {\n const options = { urlConnection: this.defaultEndpoint };\n const { resource: databaseAccount } = await this.readDatabaseAccount(diagnosticNode, options);\n return databaseAccount;\n // If for any reason(non - globaldb related), we are not able to get the database\n // account from the above call to readDatabaseAccount,\n // we would try to get this information from any of the preferred locations that the user\n // might have specified (by creating a locational endpoint)\n // and keeping eating the exception until we get the database account and return None at the end,\n // if we are not able to get that info from any endpoints\n } catch (err: any) {\n // TODO: Tracing\n }\n\n if (this.preferredLocations) {\n for (const location of this.preferredLocations) {\n try {\n const locationalEndpoint = GlobalEndpointManager.getLocationalEndpoint(\n this.defaultEndpoint,\n location,\n );\n const options = { urlConnection: locationalEndpoint };\n const { resource: databaseAccount } = await this.readDatabaseAccount(\n diagnosticNode,\n options,\n );\n if (databaseAccount) {\n return databaseAccount;\n }\n } catch (err: any) {\n // TODO: Tracing\n }\n }\n }\n }\n\n /**\n * Gets the locational endpoint using the location name passed to it using the default endpoint.\n *\n * @param defaultEndpoint - The default endpoint to use for the endpoint.\n * @param locationName - The location name for the azure region like \"East US\".\n */\n private static getLocationalEndpoint(defaultEndpoint: string, locationName: string): string {\n // For defaultEndpoint like 'https://contoso.documents.azure.com:443/' parse it to generate URL format\n // This defaultEndpoint should be global endpoint(and cannot be a locational endpoint)\n // and we agreed to document that\n const endpointUrl = new URL(defaultEndpoint);\n\n // hostname attribute in endpointUrl will return 'contoso.documents.azure.com'\n if (endpointUrl.hostname) {\n const hostnameParts = endpointUrl.hostname.toString().toLowerCase().split(\".\");\n if (hostnameParts) {\n // globalDatabaseAccountName will return 'contoso'\n const globalDatabaseAccountName = hostnameParts[0];\n\n // Prepare the locationalDatabaseAccountName as contoso-EastUS for location_name 'East US'\n const locationalDatabaseAccountName =\n globalDatabaseAccountName + \"-\" + locationName.replace(\" \", \"\");\n\n // Replace 'contoso' with 'contoso-EastUS' and\n // return locationalEndpoint as https://contoso-EastUS.documents.azure.com:443/\n const locationalEndpoint = defaultEndpoint\n .toLowerCase()\n .replace(globalDatabaseAccountName, locationalDatabaseAccountName);\n return locationalEndpoint;\n }\n }\n\n return null;\n }\n\n /**\n * Refreshes the enablePartitionLevelFailover and enablePartitionLevelCircuitBreaker flag\n * based on the value from database account.\n * @param enablePerPartitionFailover - value from database account\n */\n private refreshPPAFFeatureFlag(enablePerPartitionFailover: boolean): void {\n // If the enablePartitionLevelFailover is true, but PPAF is not enabled on the account,\n // we will override it to false.\n if (enablePerPartitionFailover === false) {\n this.enablePartitionLevelFailover = enablePerPartitionFailover;\n this.enablePartitionLevelCircuitBreaker = enablePerPartitionFailover;\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"globalEndpointManager.js","sourceRoot":"","sources":["../../src/globalEndpointManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport { OperationType, ResourceType, isReadRequest } from \"./common/index.js\";\nimport type { CosmosClientOptions } from \"./CosmosClientOptions.js\";\nimport type { Location, DatabaseAccount } from \"./documents/index.js\";\nimport type { RequestOptions } from \"./index.js\";\nimport type { ResolveServiceEndpointOptions } from \"./GlobalEndpointManagerOptions.js\";\nimport { Constants } from \"./common/constants.js\";\nimport type { ResourceResponse } from \"./request/index.js\";\nimport { MetadataLookUpType } from \"./CosmosDiagnostics.js\";\nimport type { DiagnosticNodeInternal } from \"./diagnostics/DiagnosticNodeInternal.js\";\nimport { withMetadataDiagnostics } from \"./utils/diagnostics.js\";\nimport { normalizeEndpoint } from \"./utils/checkURL.js\";\nimport { canApplyExcludedLocations } from \"./common/helper.js\";\n\n/**\n * @hidden\n * This internal class implements the logic for endpoint management for geo-replicated database accounts.\n */\nexport class GlobalEndpointManager {\n /**\n * The endpoint used to create the client instance.\n */\n private defaultEndpoint: string;\n /**\n * Flag to enable/disable automatic redirecting of requests based on read/write operations.\n */\n public enableEndpointDiscovery: boolean;\n private isRefreshing: boolean;\n private options: CosmosClientOptions;\n /**\n * List of azure regions to be used as preferred locations for read requests.\n */\n private preferredLocations: string[];\n private writeableLocations: Location[] = [];\n private readableLocations: Location[] = [];\n private unavailableReadableLocations: Location[] = [];\n private unavailableWriteableLocations: Location[] = [];\n private enableMultipleWriteLocations: boolean;\n\n public preferredLocationsCount: number;\n /**\n * Flag to enable/disable the Per Partition Level Failover (PPAF). Contains the value from the Connection policy.\n * @internal\n */\n private enablePartitionLevelFailover: boolean;\n /**\n * Flag to enable/disable the Per Partition Level Circuit Breaker (PPCB). Contains the value from the Connection policy.\n * @internal\n */\n private enablePartitionLevelCircuitBreaker: boolean;\n /**\n * Cached PPAF enablement status from the last account refresh\n * @internal\n */\n public lastKnownPPAFEnabled: boolean;\n /**\n * Cached circuit breaker timer enablement status\n * @internal\n */\n public lastKnownPPCBEnabled: boolean;\n /**\n * Event that is raised when circuit breaker timer should start or stop based on PPAF/PPCB status changes\n * @internal\n */\n public onEnablePartitionLevelFailoverConfigChanged?: (isEnabled: boolean) => void;\n\n /**\n * @param options - The document client instance.\n * @internal\n */\n constructor(\n options: CosmosClientOptions,\n private readDatabaseAccount: (\n diagnosticNode: DiagnosticNodeInternal,\n opts: RequestOptions,\n ) => Promise<ResourceResponse<DatabaseAccount>>,\n ) {\n this.options = options;\n this.defaultEndpoint = options.endpoint;\n this.enableEndpointDiscovery = options.connectionPolicy.enableEndpointDiscovery;\n this.isRefreshing = false;\n this.preferredLocations = this.options.connectionPolicy.preferredLocations;\n this.preferredLocationsCount = this.preferredLocations ? this.preferredLocations.length : 0;\n this.enablePartitionLevelFailover = options.connectionPolicy.enablePartitionLevelFailover;\n this.enablePartitionLevelCircuitBreaker =\n options.connectionPolicy.enablePartitionLevelCircuitBreaker;\n this.lastKnownPPCBEnabled = options.connectionPolicy.enablePartitionLevelCircuitBreaker;\n this.lastKnownPPAFEnabled = false;\n }\n\n /**\n * Gets the current read endpoint from the endpoint cache.\n */\n public async getReadEndpoint(diagnosticNode: DiagnosticNodeInternal): Promise<string> {\n return this.resolveServiceEndpoint(diagnosticNode, ResourceType.item, OperationType.Read);\n }\n\n /**\n * Gets the current write endpoint from the endpoint cache.\n */\n public async getWriteEndpoint(diagnosticNode: DiagnosticNodeInternal): Promise<string> {\n return this.resolveServiceEndpoint(diagnosticNode, ResourceType.item, OperationType.Replace);\n }\n\n public async getReadEndpoints(): Promise<ReadonlyArray<string>> {\n return this.readableLocations.map((loc) => loc.databaseAccountEndpoint);\n }\n\n public async getWriteEndpoints(): Promise<ReadonlyArray<string>> {\n return this.writeableLocations.map((loc) => loc.databaseAccountEndpoint);\n }\n\n /**\n * Gets the read locations from the endpoint cache.\n */\n public async getReadLocations(): Promise<ReadonlyArray<Location>> {\n return this.readableLocations;\n }\n\n public async markCurrentLocationUnavailableForRead(\n diagnosticNode: DiagnosticNodeInternal,\n endpoint: string,\n ): Promise<void> {\n await this.refreshEndpointList(diagnosticNode);\n const location = this.readableLocations.find((loc) => loc.databaseAccountEndpoint === endpoint);\n if (location) {\n location.unavailable = true;\n location.lastUnavailabilityTimestampInMs = Date.now();\n this.unavailableReadableLocations.push(location);\n }\n }\n\n public async markCurrentLocationUnavailableForWrite(\n diagnosticNode: DiagnosticNodeInternal,\n endpoint: string,\n ): Promise<void> {\n await this.refreshEndpointList(diagnosticNode);\n const location = this.writeableLocations.find(\n (loc) => loc.databaseAccountEndpoint === endpoint,\n );\n if (location) {\n location.unavailable = true;\n location.lastUnavailabilityTimestampInMs = Date.now();\n this.unavailableWriteableLocations.push(location);\n }\n }\n\n public canUseMultipleWriteLocations(\n resourceType?: ResourceType,\n operationType?: OperationType,\n ): boolean {\n let canUse =\n this.options.connectionPolicy.useMultipleWriteLocations && this.enableMultipleWriteLocations;\n\n if (resourceType) {\n canUse =\n canUse &&\n (resourceType === ResourceType.item ||\n (resourceType === ResourceType.sproc && operationType === OperationType.Execute));\n }\n\n return canUse;\n }\n\n private getEffectiveExcludedLocations(\n excludedLocations: string[] = [],\n resourceType: ResourceType,\n ): Set<string> {\n if (!canApplyExcludedLocations(resourceType)) {\n return new Set();\n }\n\n return excludedLocations.length ? new Set(excludedLocations.map(normalizeEndpoint)) : new Set();\n }\n\n private filterExcludedLocations(\n preferredLocations: string[],\n excludedLocations?: Set<string>,\n ): string[] {\n if (!excludedLocations || excludedLocations.size === 0) {\n return preferredLocations;\n }\n const filteredLocations = preferredLocations.filter((location) => {\n return !excludedLocations.has(normalizeEndpoint(location));\n });\n return filteredLocations;\n }\n\n public async resolveServiceEndpoint(\n diagnosticNode: DiagnosticNodeInternal,\n resourceType: ResourceType,\n operationType: OperationType,\n startServiceEndpointIndex: number = 0, // Represents the starting index for selecting servers.\n ): Promise<string> {\n return this.resolveServiceEndpointInternal({\n diagnosticNode: diagnosticNode,\n resourceType: resourceType,\n operationType: operationType,\n startServiceEndpointIndex: startServiceEndpointIndex,\n });\n }\n\n /**\n * @internal\n */\n public async resolveServiceEndpointInternal(\n resolveServiceEndpointOptions: ResolveServiceEndpointOptions,\n ): Promise<string> {\n // Extract all fields from ResolveServiceEndpointOptions\n const {\n diagnosticNode,\n resourceType,\n operationType,\n startServiceEndpointIndex,\n excludedLocations = [],\n } = resolveServiceEndpointOptions;\n\n // If endpoint discovery is disabled, always use the user provided endpoint\n\n if (!this.options.connectionPolicy.enableEndpointDiscovery) {\n diagnosticNode.addData({ readFromCache: true }, \"default_endpoint\");\n diagnosticNode.recordEndpointResolution(this.defaultEndpoint);\n return this.defaultEndpoint;\n }\n\n // If getting the database account, always use the user provided endpoint\n if (resourceType === ResourceType.none) {\n diagnosticNode.addData({ readFromCache: true }, \"none_resource\");\n diagnosticNode.recordEndpointResolution(this.defaultEndpoint);\n return this.defaultEndpoint;\n }\n if (this.readableLocations.length === 0 || this.writeableLocations.length === 0) {\n const resourceResponse = await withMetadataDiagnostics(\n async (metadataNode: DiagnosticNodeInternal) => {\n return this.readDatabaseAccount(metadataNode, {\n urlConnection: this.defaultEndpoint,\n });\n },\n diagnosticNode,\n MetadataLookUpType.DatabaseAccountLookUp,\n );\n\n this.writeableLocations = resourceResponse.resource.writableLocations;\n this.readableLocations = resourceResponse.resource.readableLocations;\n this.enableMultipleWriteLocations = resourceResponse.resource.enableMultipleWritableLocations;\n if (this.enablePartitionLevelFailover) {\n this.refreshPPAFFeatureFlag(resourceResponse.resource);\n }\n }\n\n const locations = isReadRequest(operationType)\n ? this.readableLocations\n : this.writeableLocations;\n\n const effectiveExcludedLocations = this.getEffectiveExcludedLocations(\n excludedLocations,\n resourceType,\n );\n diagnosticNode.addData(\n { excludedLocations: Array.from(effectiveExcludedLocations) },\n \"excluded_locations\",\n );\n\n // Filter locations based on exclusions\n const availableLocations = this.filterExcludedLocations(\n this.preferredLocations,\n effectiveExcludedLocations,\n );\n\n let location;\n // If we have preferred locations, try each one in order and use the first available one\n if (\n availableLocations &&\n availableLocations.length > 0 &&\n startServiceEndpointIndex < availableLocations.length\n ) {\n this.preferredLocationsCount = availableLocations.length;\n\n for (let i = startServiceEndpointIndex; i < availableLocations.length; i++) {\n const preferredLocation = availableLocations[i];\n location = locations.find(\n (loc) =>\n loc.unavailable !== true &&\n normalizeEndpoint(loc.name) === normalizeEndpoint(preferredLocation),\n );\n if (location) {\n break;\n }\n }\n }\n\n // If no preferred locations or one did not match, just grab the first one that is available\n if (!location) {\n const startIndexValid =\n startServiceEndpointIndex >= 0 && startServiceEndpointIndex < locations.length;\n const locationsToSearch = startIndexValid\n ? locations.slice(startServiceEndpointIndex)\n : locations;\n location = locationsToSearch.find((loc) => {\n return (\n loc.unavailable !== true && !effectiveExcludedLocations.has(normalizeEndpoint(loc.name))\n );\n });\n }\n\n location = location ? location : { name: \"\", databaseAccountEndpoint: this.defaultEndpoint };\n diagnosticNode.recordEndpointResolution(location.databaseAccountEndpoint);\n return location.databaseAccountEndpoint;\n }\n\n /**\n * Refreshes the endpoint list by clearning stale unavailability and then\n * retrieving the writable and readable locations from the geo-replicated database account\n * and then updating the locations cache.\n * We skip the refreshing if enableEndpointDiscovery is set to False\n */\n public async refreshEndpointList(diagnosticNode: DiagnosticNodeInternal): Promise<void> {\n if (!this.isRefreshing && this.enableEndpointDiscovery) {\n this.isRefreshing = true;\n const databaseAccount = await this.getDatabaseAccountFromAnyEndpoint(diagnosticNode);\n if (databaseAccount) {\n if (this.enablePartitionLevelFailover) {\n this.refreshPPAFFeatureFlag(databaseAccount);\n }\n this.refreshStaleUnavailableLocations();\n this.refreshEndpoints(databaseAccount);\n }\n this.isRefreshing = false;\n }\n }\n\n private refreshEndpoints(databaseAccount: DatabaseAccount): void {\n const oldWritableLocations = this.writeableLocations;\n const oldReadableLocations = this.readableLocations;\n\n function merge(loc: Location, oldList: Location[]): Location {\n const prev = oldList.find((o) => o.name === loc.name);\n if (prev) {\n loc.unavailable = prev.unavailable;\n loc.lastUnavailabilityTimestampInMs = prev.lastUnavailabilityTimestampInMs;\n }\n return loc;\n }\n\n this.writeableLocations = databaseAccount.writableLocations.map((loc) =>\n merge({ ...loc }, oldWritableLocations),\n );\n this.readableLocations = databaseAccount.readableLocations.map((loc) =>\n merge({ ...loc }, oldReadableLocations),\n );\n }\n\n private refreshStaleUnavailableLocations(): void {\n const now = Date.now();\n this.updateLocation(now, this.unavailableReadableLocations, this.readableLocations);\n this.unavailableReadableLocations = this.cleanUnavailableLocationList(\n now,\n this.unavailableReadableLocations,\n );\n\n this.updateLocation(now, this.unavailableWriteableLocations, this.writeableLocations);\n this.unavailableWriteableLocations = this.cleanUnavailableLocationList(\n now,\n this.unavailableWriteableLocations,\n );\n }\n\n /**\n * update the locationUnavailability to undefined if the location is available again\n * @param now - current time\n * @param unavailableLocations - list of unavailable locations\n * @param allLocations - list of all locations\n */\n private updateLocation(\n now: number,\n unavailableLocations: Location[],\n allLocations: Location[],\n ): void {\n for (const location of unavailableLocations) {\n const unavailableLocation = allLocations.find((loc) => loc.name === location.name);\n if (\n unavailableLocation &&\n now - unavailableLocation.lastUnavailabilityTimestampInMs >\n Constants.LocationUnavailableExpirationTimeInMs\n ) {\n unavailableLocation.unavailable = false;\n }\n }\n }\n\n private cleanUnavailableLocationList(now: number, unavailableLocations: Location[]): Location[] {\n return unavailableLocations.filter((loc) => {\n return (\n now - loc.lastUnavailabilityTimestampInMs < Constants.LocationUnavailableExpirationTimeInMs\n );\n });\n }\n\n /**\n * Gets the database account first by using the default endpoint, and if that doesn't returns\n * use the endpoints for the preferred locations in the order they are specified to get\n * the database account.\n */\n private async getDatabaseAccountFromAnyEndpoint(\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<DatabaseAccount> {\n try {\n const options = { urlConnection: this.defaultEndpoint };\n const { resource: databaseAccount } = await this.readDatabaseAccount(diagnosticNode, options);\n return databaseAccount;\n // If for any reason(non - globaldb related), we are not able to get the database\n // account from the above call to readDatabaseAccount,\n // we would try to get this information from any of the preferred locations that the user\n // might have specified (by creating a locational endpoint)\n // and keeping eating the exception until we get the database account and return None at the end,\n // if we are not able to get that info from any endpoints\n } catch (err: any) {\n // TODO: Tracing\n }\n\n if (this.preferredLocations) {\n for (const location of this.preferredLocations) {\n try {\n const locationalEndpoint = GlobalEndpointManager.getLocationalEndpoint(\n this.defaultEndpoint,\n location,\n );\n const options = { urlConnection: locationalEndpoint };\n const { resource: databaseAccount } = await this.readDatabaseAccount(\n diagnosticNode,\n options,\n );\n if (databaseAccount) {\n return databaseAccount;\n }\n } catch (err: any) {\n // TODO: Tracing\n }\n }\n }\n }\n\n /**\n * Gets the locational endpoint using the location name passed to it using the default endpoint.\n *\n * @param defaultEndpoint - The default endpoint to use for the endpoint.\n * @param locationName - The location name for the azure region like \"East US\".\n */\n private static getLocationalEndpoint(defaultEndpoint: string, locationName: string): string {\n // For defaultEndpoint like 'https://contoso.documents.azure.com:443/' parse it to generate URL format\n // This defaultEndpoint should be global endpoint(and cannot be a locational endpoint)\n // and we agreed to document that\n const endpointUrl = new URL(defaultEndpoint);\n\n // hostname attribute in endpointUrl will return 'contoso.documents.azure.com'\n if (endpointUrl.hostname) {\n const hostnameParts = endpointUrl.hostname.toString().toLowerCase().split(\".\");\n if (hostnameParts) {\n // globalDatabaseAccountName will return 'contoso'\n const globalDatabaseAccountName = hostnameParts[0];\n\n // Prepare the locationalDatabaseAccountName as contoso-EastUS for location_name 'East US'\n const locationalDatabaseAccountName =\n globalDatabaseAccountName + \"-\" + locationName.replace(\" \", \"\");\n\n // Replace 'contoso' with 'contoso-EastUS' and\n // return locationalEndpoint as https://contoso-EastUS.documents.azure.com:443/\n const locationalEndpoint = defaultEndpoint\n .toLowerCase()\n .replace(globalDatabaseAccountName, locationalDatabaseAccountName);\n return locationalEndpoint;\n }\n }\n\n return null;\n }\n\n /**\n * Checks for changes in PPAF enablement status and raises events if they have changed.\n * It also manages circuit breaker timer state.\n * @internal\n */\n private refreshPPAFFeatureFlag(databaseAccount: DatabaseAccount): void {\n let shouldEnableCircuitBreakerTimer = false;\n if (this.enablePartitionLevelCircuitBreaker) {\n // If PPCB is enabled in connection policy, always run circuit breaker\n shouldEnableCircuitBreakerTimer = true;\n } else {\n // If PPCB is disabled, circuit breaker timer depends on PPAF flags\n if (!this.enablePartitionLevelFailover) {\n // If PPAF is disabled in connection policy, don't run circuit breaker ever.\n shouldEnableCircuitBreakerTimer = false;\n } else {\n shouldEnableCircuitBreakerTimer =\n databaseAccount.enablePerPartitionFailover ?? this.lastKnownPPAFEnabled ?? false;\n }\n }\n\n this.lastKnownPPAFEnabled = databaseAccount.enablePerPartitionFailover;\n\n // Only trigger callback if the circuit breaker timer state has changed\n if (this.lastKnownPPCBEnabled !== shouldEnableCircuitBreakerTimer) {\n this.lastKnownPPCBEnabled = shouldEnableCircuitBreakerTimer;\n this.onEnablePartitionLevelFailoverConfigChanged?.(shouldEnableCircuitBreakerTimer);\n }\n }\n}\n"]}
|
|
@@ -9,7 +9,7 @@ export declare class GlobalPartitionEndpointManager {
|
|
|
9
9
|
private readonly partitionKeyRangeToLocationForReadAndWrite;
|
|
10
10
|
private preferredLocations;
|
|
11
11
|
preferredLocationsCount: number;
|
|
12
|
-
private circuitBreakerFailbackBackgroundRefresher
|
|
12
|
+
private circuitBreakerFailbackBackgroundRefresher?;
|
|
13
13
|
/**
|
|
14
14
|
* Checks eligibility of the request for partition failover and
|
|
15
15
|
* tries to mark the endpoint unavailable for the partition key range. Future
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalPartitionEndpointManager.d.ts","sourceRoot":"","sources":["../../src/globalPartitionEndpointManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,sBAAsB,EAGtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,qBAAa,8BAA8B;IAevC,OAAO,CAAC,qBAAqB;IAd/B,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAA6C;IACjG,OAAO,CAAC,QAAQ,CAAC,0CAA0C,CAGzD;IACF,OAAO,CAAC,kBAAkB,CAAW;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IACvC,OAAO,CAAC,yCAAyC,CAAiB;
|
|
1
|
+
{"version":3,"file":"globalPartitionEndpointManager.d.ts","sourceRoot":"","sources":["../../src/globalPartitionEndpointManager.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,sBAAsB,EAGtB,KAAK,cAAc,EACpB,MAAM,YAAY,CAAC;AAMpB;;;GAGG;AACH,qBAAa,8BAA8B;IAevC,OAAO,CAAC,qBAAqB;IAd/B,OAAO,CAAC,QAAQ,CAAC,mCAAmC,CAA6C;IACjG,OAAO,CAAC,QAAQ,CAAC,0CAA0C,CAGzD;IACF,OAAO,CAAC,kBAAkB,CAAW;IAC9B,uBAAuB,EAAE,MAAM,CAAC;IACvC,OAAO,CAAC,yCAAyC,CAAC,CAAiB;IAqBnE;;;;OAIG;IACU,yBAAyB,CACpC,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,sBAAsB,GACrC,OAAO,CAAC,OAAO,CAAC;IA6BnB;;;OAGG;IACU,oCAAoC,CAC/C,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,sBAAsB,GACrC,OAAO,CAAC,cAAc,CAAC;IAiC1B;;;OAGG;IACI,OAAO,IAAI,IAAI;YAOR,8CAA8C;IA2D5D;;;OAGG;YACW,uCAAuC;IA6CrD,yEAAyE;YAC3D,qCAAqC;IA2BnD,0FAA0F;YAC5E,qCAAqC;IAmBnD;;;;OAIG;IACH,OAAO,CAAC,iDAAiD;IAazD;;;;OAIG;IACH,OAAO,CAAC,gDAAgD;IAgBxD;;;;;;OAMG;YACW,wDAAwD;IA8BtE;;;;;;;;OAQG;IACH,OAAO,CAAC,kCAAkC;IAU1C;;;;;OAKG;YACW,8CAA8C;CAqD7D"}
|
|
@@ -29,8 +29,7 @@ class GlobalPartitionEndpointManager {
|
|
|
29
29
|
this.partitionKeyRangeToLocationForReadAndWrite = new Map();
|
|
30
30
|
this.preferredLocations = options.connectionPolicy.preferredLocations;
|
|
31
31
|
this.preferredLocationsCount = this.preferredLocations ? this.preferredLocations.length : 0;
|
|
32
|
-
if (this.globalEndpointManager.
|
|
33
|
-
this.globalEndpointManager.enablePartitionLevelFailover) {
|
|
32
|
+
if (this.globalEndpointManager.lastKnownPPCBEnabled) {
|
|
34
33
|
this.initiateCircuitBreakerFailbackLoop();
|
|
35
34
|
}
|
|
36
35
|
}
|
|
@@ -89,6 +88,7 @@ class GlobalPartitionEndpointManager {
|
|
|
89
88
|
dispose() {
|
|
90
89
|
if (this.circuitBreakerFailbackBackgroundRefresher) {
|
|
91
90
|
clearTimeout(this.circuitBreakerFailbackBackgroundRefresher);
|
|
91
|
+
this.circuitBreakerFailbackBackgroundRefresher = undefined;
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
async tryMarkEndpointUnavailableForPartitionKeyRange(requestContext, diagnosticNode, isRequestEligibleForPerPartitionAutomaticFailover, isRequestEligibleForPartitionLevelCircuitBreaker) {
|
|
@@ -200,7 +200,7 @@ class GlobalPartitionEndpointManager {
|
|
|
200
200
|
* and the global endpoint manager cannot use multiple write locations for the request.
|
|
201
201
|
*/
|
|
202
202
|
isRequestEligibleForPerPartitionAutomaticFailover(requestContext) {
|
|
203
|
-
return (this.
|
|
203
|
+
return (this.isPartitionLevelAutomaticFailoverEnabled() &&
|
|
204
204
|
!(0, index_js_1.isReadRequest)(requestContext.operationType) &&
|
|
205
205
|
!this.globalEndpointManager.canUseMultipleWriteLocations(requestContext.resourceType, requestContext.operationType));
|
|
206
206
|
}
|
|
@@ -210,8 +210,7 @@ class GlobalPartitionEndpointManager {
|
|
|
210
210
|
* the global endpoint manager can use multiple write locations for the request.
|
|
211
211
|
*/
|
|
212
212
|
isRequestEligibleForPartitionLevelCircuitBreaker(requestContext) {
|
|
213
|
-
const enablePartitionLevelCircuitBreaker = this.
|
|
214
|
-
this.globalEndpointManager.enablePartitionLevelFailover;
|
|
213
|
+
const enablePartitionLevelCircuitBreaker = this.isPartitionLevelCircuitBreakerEnabled();
|
|
215
214
|
if (!enablePartitionLevelCircuitBreaker) {
|
|
216
215
|
return false;
|
|
217
216
|
}
|
|
@@ -269,12 +268,6 @@ class GlobalPartitionEndpointManager {
|
|
|
269
268
|
*/
|
|
270
269
|
async openConnectionToUnhealthyEndpointsWithFailback() {
|
|
271
270
|
// If partition level circuit breaker or failover is not enabled, dispose the timer.
|
|
272
|
-
const enablePartitionLevelCircuitBreaker = this.globalEndpointManager.enablePartitionLevelCircuitBreaker ||
|
|
273
|
-
this.globalEndpointManager.enablePartitionLevelFailover;
|
|
274
|
-
if (!enablePartitionLevelCircuitBreaker) {
|
|
275
|
-
this.dispose();
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
271
|
for (const pkRange of this.partitionKeyRangeToLocationForReadAndWrite.keys()) {
|
|
279
272
|
const partitionFailover = this.partitionKeyRangeToLocationForReadAndWrite.get(pkRange);
|
|
280
273
|
if (!partitionFailover)
|
|
@@ -289,6 +282,38 @@ class GlobalPartitionEndpointManager {
|
|
|
289
282
|
}
|
|
290
283
|
}
|
|
291
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* @internal
|
|
287
|
+
*/
|
|
288
|
+
changeCircuitBreakerFailbackLoop(isEnabled) {
|
|
289
|
+
// Start or stop the circuit breaker failback loop based on PPAF/PPCB status
|
|
290
|
+
if (isEnabled) {
|
|
291
|
+
// Only start if not already running to prevent duplicate timers
|
|
292
|
+
if (!this.circuitBreakerFailbackBackgroundRefresher) {
|
|
293
|
+
this.initiateCircuitBreakerFailbackLoop();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
// Only dispose if currently running
|
|
298
|
+
if (this.circuitBreakerFailbackBackgroundRefresher) {
|
|
299
|
+
this.dispose();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Gets a value indicating whether per-partition automatic failover is currently enabled.
|
|
305
|
+
* @internal
|
|
306
|
+
*/
|
|
307
|
+
isPartitionLevelAutomaticFailoverEnabled() {
|
|
308
|
+
return this.globalEndpointManager.lastKnownPPAFEnabled;
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Gets a value indicating whether per-partition automatic failover is currently enabled.
|
|
312
|
+
* @internal
|
|
313
|
+
*/
|
|
314
|
+
isPartitionLevelCircuitBreakerEnabled() {
|
|
315
|
+
return this.globalEndpointManager.lastKnownPPCBEnabled;
|
|
316
|
+
}
|
|
292
317
|
}
|
|
293
318
|
exports.GlobalPartitionEndpointManager = GlobalPartitionEndpointManager;
|
|
294
319
|
//# sourceMappingURL=globalPartitionEndpointManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalPartitionEndpointManager.js","sourceRoot":"","sources":["../../src/globalPartitionEndpointManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport { OperationType, ResourceType, isReadRequest } from \"./common/index.js\";\nimport {\n Constants,\n DiagnosticNodeInternal,\n type CosmosClientOptions,\n type GlobalEndpointManager,\n type RequestContext,\n} from \"./index.js\";\nimport { PartitionKeyRangeFailoverInfo } from \"./PartitionKeyRangeFailoverInfo.js\";\nimport { normalizeEndpoint } from \"./utils/checkURL.js\";\nimport { startBackgroundTask } from \"./utils/time.js\";\nimport { assertNotUndefined } from \"./utils/typeChecks.js\";\n\n/**\n * @hidden\n * This class is used to failover single partitions to different regions.\n */\nexport class GlobalPartitionEndpointManager {\n private readonly partitionKeyRangeToLocationForWrite: Map<string, PartitionKeyRangeFailoverInfo>;\n private readonly partitionKeyRangeToLocationForReadAndWrite: Map<\n string,\n PartitionKeyRangeFailoverInfo\n >;\n private preferredLocations: string[];\n public preferredLocationsCount: number;\n private circuitBreakerFailbackBackgroundRefresher: NodeJS.Timeout;\n\n /**\n * @internal\n */\n constructor(\n options: CosmosClientOptions,\n private globalEndpointManager: GlobalEndpointManager,\n ) {\n this.partitionKeyRangeToLocationForWrite = new Map<string, PartitionKeyRangeFailoverInfo>();\n this.partitionKeyRangeToLocationForReadAndWrite = new Map<\n string,\n PartitionKeyRangeFailoverInfo\n >();\n this.preferredLocations = options.connectionPolicy.preferredLocations;\n this.preferredLocationsCount = this.preferredLocations ? this.preferredLocations.length : 0;\n if (\n this.globalEndpointManager.enablePartitionLevelCircuitBreaker ||\n this.globalEndpointManager.enablePartitionLevelFailover\n ) {\n this.initiateCircuitBreakerFailbackLoop();\n }\n }\n\n /**\n * Checks eligibility of the request for partition failover and\n * tries to mark the endpoint unavailable for the partition key range. Future\n * requests will be routed to the next location if available.\n */\n public async tryPartitionLevelFailover(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<boolean> {\n if (!(await this.isRequestEligibleForPartitionFailover(requestContext, true))) {\n return false;\n }\n\n const isRequestEligibleForPerPartitionAutomaticFailover =\n this.isRequestEligibleForPerPartitionAutomaticFailover(requestContext);\n const isRequestEligibleForPartitionLevelCircuitBreaker =\n this.isRequestEligibleForPartitionLevelCircuitBreaker(requestContext);\n\n if (\n isRequestEligibleForPerPartitionAutomaticFailover ||\n (isRequestEligibleForPartitionLevelCircuitBreaker &&\n (await this.incrementFailureCounterAndCheckFailover(\n requestContext,\n isRequestEligibleForPerPartitionAutomaticFailover,\n isRequestEligibleForPartitionLevelCircuitBreaker,\n )))\n ) {\n return this.tryMarkEndpointUnavailableForPartitionKeyRange(\n requestContext,\n diagnosticNode,\n isRequestEligibleForPerPartitionAutomaticFailover,\n isRequestEligibleForPartitionLevelCircuitBreaker,\n );\n }\n return false;\n }\n\n /**\n * Updates the DocumentServiceRequest routing location to point\n * new a location based if a partition level failover occurred.\n */\n public async tryAddPartitionLevelLocationOverride(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<RequestContext> {\n if (!(await this.isRequestEligibleForPartitionFailover(requestContext, false))) {\n return requestContext;\n }\n\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n\n if (this.isRequestEligibleForPerPartitionAutomaticFailover(requestContext)) {\n if (this.partitionKeyRangeToLocationForWrite.has(partitionKeyRangeId)) {\n const partitionFailOver = this.partitionKeyRangeToLocationForWrite.get(partitionKeyRangeId);\n requestContext.endpoint = partitionFailOver.getCurrentEndPoint();\n diagnosticNode.recordEndpointResolution(requestContext.endpoint);\n return requestContext;\n }\n } else if (this.isRequestEligibleForPartitionLevelCircuitBreaker(requestContext)) {\n if (this.partitionKeyRangeToLocationForReadAndWrite.has(partitionKeyRangeId)) {\n const partitionFailOver =\n this.partitionKeyRangeToLocationForReadAndWrite.get(partitionKeyRangeId);\n\n const canCircuitBreakerTriggerPartitionFailOver =\n await partitionFailOver.canCircuitBreakerTriggerPartitionFailOver(\n isReadRequest(requestContext.operationType),\n );\n if (canCircuitBreakerTriggerPartitionFailOver) {\n requestContext.endpoint = partitionFailOver.getCurrentEndPoint();\n diagnosticNode.recordEndpointResolution(requestContext.endpoint);\n return requestContext;\n }\n }\n }\n return requestContext;\n }\n\n /**\n * This method clears the background refresher for circuit breaker failback\n * and stops the periodic checks for unhealthy endpoints.\n */\n public dispose(): void {\n if (this.circuitBreakerFailbackBackgroundRefresher) {\n clearTimeout(this.circuitBreakerFailbackBackgroundRefresher);\n }\n }\n\n private async tryMarkEndpointUnavailableForPartitionKeyRange(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n isRequestEligibleForPerPartitionAutomaticFailover: boolean,\n isRequestEligibleForPartitionLevelCircuitBreaker: boolean,\n ): Promise<boolean> {\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n const failedEndPoint = requestContext.endpoint;\n\n const readLocations = await this.globalEndpointManager.getReadLocations();\n const readEndPoints: string[] = [];\n\n if (isRequestEligibleForPerPartitionAutomaticFailover) {\n // For any single master write accounts, the next locations to fail over will be the read regions configured at the account level.\n for (const location of readLocations) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n return this.tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId,\n failedEndPoint,\n readEndPoints,\n this.partitionKeyRangeToLocationForWrite,\n diagnosticNode,\n );\n } else if (isRequestEligibleForPartitionLevelCircuitBreaker) {\n // For the read requests or multi-master write requests, the next locations to fail over will be the preferred locations\n // configured at the account level plus any other read locations that are not already in the preferred locations.\n if (this.preferredLocations && this.preferredLocations.length > 0) {\n for (const preferredLocation of this.preferredLocations) {\n const location = readLocations.find(\n (loc) => normalizeEndpoint(loc.name) === normalizeEndpoint(preferredLocation),\n );\n if (location) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n\n // Add the rest of the locations not already added\n for (const location of readLocations) {\n if (!readEndPoints.includes(location.databaseAccountEndpoint)) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n } else {\n for (const location of readLocations) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n return this.tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId,\n failedEndPoint,\n readEndPoints,\n this.partitionKeyRangeToLocationForReadAndWrite,\n diagnosticNode,\n );\n }\n return false;\n }\n\n /**\n * Increments the failure counter for the specified partition and checks if the partition can fail over.\n * This method is used to determine if a partition should be failed over based on the number of request failures.\n */\n private async incrementFailureCounterAndCheckFailover(\n requestContext: RequestContext,\n isRequestEligibleForPerPartitionAutomaticFailover: boolean,\n isRequestEligibleForPartitionLevelCircuitBreaker: boolean,\n ): Promise<boolean> {\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n const failedEndPoint = requestContext.endpoint;\n let partitionKeyRangeFailoverInfo: PartitionKeyRangeFailoverInfo;\n\n if (isRequestEligibleForPerPartitionAutomaticFailover) {\n if (!this.partitionKeyRangeToLocationForWrite.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n this.partitionKeyRangeToLocationForWrite.set(partitionKeyRangeId, failoverInfo);\n }\n partitionKeyRangeFailoverInfo =\n this.partitionKeyRangeToLocationForWrite.get(partitionKeyRangeId);\n } else if (isRequestEligibleForPartitionLevelCircuitBreaker) {\n if (!this.partitionKeyRangeToLocationForReadAndWrite.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n this.partitionKeyRangeToLocationForReadAndWrite.set(partitionKeyRangeId, failoverInfo);\n }\n partitionKeyRangeFailoverInfo =\n this.partitionKeyRangeToLocationForReadAndWrite.get(partitionKeyRangeId);\n } else {\n return false;\n }\n\n assertNotUndefined(\n partitionKeyRangeFailoverInfo,\n \"partitionKeyRangeFailoverInfo should be set if failover flags are true.\",\n );\n\n const currentTimeInMilliseconds = Date.now();\n await partitionKeyRangeFailoverInfo.incrementRequestFailureCounts(\n isReadRequest(requestContext.operationType),\n currentTimeInMilliseconds,\n );\n\n return partitionKeyRangeFailoverInfo.canCircuitBreakerTriggerPartitionFailOver(\n isReadRequest(requestContext.operationType),\n );\n }\n\n /** Validates if the given request is eligible for partition failover. */\n private async isRequestEligibleForPartitionFailover(\n requestContext: RequestContext,\n shouldValidateFailedLocation: boolean,\n ): Promise<boolean> {\n if (\n !requestContext ||\n !requestContext.operationType ||\n !requestContext.resourceType ||\n !requestContext.partitionKeyRangeId\n ) {\n return false;\n }\n\n const canUsePartitionLevelFailoverLocations = await this.canUsePartitionLevelFailoverLocations(\n requestContext.operationType,\n requestContext.resourceType,\n );\n if (!canUsePartitionLevelFailoverLocations) {\n return false;\n }\n\n if (shouldValidateFailedLocation && !requestContext.endpoint) {\n return false;\n }\n return true;\n }\n\n /** Determines if partition level failover locations can be used for the given request. */\n private async canUsePartitionLevelFailoverLocations(\n operationType?: OperationType,\n resourceType?: ResourceType,\n ): Promise<boolean> {\n const readEndPoints = await this.globalEndpointManager.getReadEndpoints();\n if (readEndPoints.length <= 1) {\n return false;\n }\n if (\n resourceType === ResourceType.item ||\n (resourceType === ResourceType.sproc && operationType === OperationType.Execute)\n ) {\n // Right now, for single-master only reads are supported for circuit breaker, and writes are supported for automatic.\n // failover. For multi master, both reads and writes are supported. Hence return true for both the cases.\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a request is eligible for per-partition automatic failover.\n * A request is eligible if it is a write request, partition level failover is enabled,\n * and the global endpoint manager cannot use multiple write locations for the request.\n */\n private isRequestEligibleForPerPartitionAutomaticFailover(\n requestContext: RequestContext,\n ): boolean {\n return (\n this.globalEndpointManager.enablePartitionLevelFailover &&\n !isReadRequest(requestContext.operationType) &&\n !this.globalEndpointManager.canUseMultipleWriteLocations(\n requestContext.resourceType,\n requestContext.operationType,\n )\n );\n }\n\n /**\n * Determines if a request is eligible for partition-level circuit breaker.\n * This method checks if partition-level circuit breaker is enabled, and if the request is a read-only request or\n * the global endpoint manager can use multiple write locations for the request.\n */\n private isRequestEligibleForPartitionLevelCircuitBreaker(\n requestContext: RequestContext,\n ): boolean {\n const enablePartitionLevelCircuitBreaker =\n this.globalEndpointManager.enablePartitionLevelCircuitBreaker ||\n this.globalEndpointManager.enablePartitionLevelFailover;\n if (!enablePartitionLevelCircuitBreaker) {\n return false;\n }\n if (isReadRequest(requestContext.operationType)) {\n return true;\n }\n return this.globalEndpointManager.canUseMultipleWriteLocations(\n requestContext.resourceType,\n requestContext.operationType,\n );\n }\n\n /**\n * Attempts to add or update the partition failover information and move to the next available location.\n * This method checks if the current location for the partition key range has failed and updates the failover\n * information to route the request to the next available location. If all locations have been tried, it removes\n * the failover information for the partition key range. Return True if the failover information was successfully\n * updated and the request was routed to a new location, otherwise false.\n */\n private async tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId: string,\n failedEndPoint: string,\n nextEndPoints: readonly string[],\n partitionKeyRangeToLocation: Map<string, PartitionKeyRangeFailoverInfo>,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<boolean> {\n if (!partitionKeyRangeToLocation.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n partitionKeyRangeToLocation.set(partitionKeyRangeId, failoverInfo);\n }\n const partitionFailOver = partitionKeyRangeToLocation.get(partitionKeyRangeId);\n\n // Will return true if it was able to update to a new region\n if (\n await partitionFailOver.tryMoveNextLocation(\n nextEndPoints,\n failedEndPoint,\n diagnosticNode,\n partitionKeyRangeId,\n )\n ) {\n return true;\n }\n // All the locations have been tried. Remove the override information\n partitionKeyRangeToLocation.delete(partitionKeyRangeId);\n return false;\n }\n\n /**\n * Initiates a background loop that periodically checks for unhealthy endpoints\n * and attempts to open connections to them. If a connection is successfully\n * established, it initiates a failback to the original location for the partition key range.\n * This is useful for scenarios where a partition key range has been marked as unavailable\n * due to a circuit breaker, and we want to periodically check if the original location\n * has become healthy again.\n * The loop runs at a defined interval specified by Constants.StalePartitionUnavailabilityRefreshIntervalInMs.\n */\n private initiateCircuitBreakerFailbackLoop(): void {\n this.circuitBreakerFailbackBackgroundRefresher = startBackgroundTask(async () => {\n try {\n await this.openConnectionToUnhealthyEndpointsWithFailback();\n } catch (err) {\n console.error(\"Failed to open connection to unhealthy endpoints: \", err);\n }\n }, Constants.StalePartitionUnavailabilityRefreshIntervalInMs);\n }\n\n /**\n * Attempts to open connections to unhealthy endpoints and initiates failback if the connections are successful.\n * This method checks the partition key ranges that have failed locations and tries to re-establish connections\n * to those locations. If a connection is successfully re-established, it initiates a failback to the original\n * location for the partition key range.\n */\n private async openConnectionToUnhealthyEndpointsWithFailback(): Promise<void> {\n // If partition level circuit breaker or failover is not enabled, dispose the timer.\n const enablePartitionLevelCircuitBreaker =\n this.globalEndpointManager.enablePartitionLevelCircuitBreaker ||\n this.globalEndpointManager.enablePartitionLevelFailover;\n if (!enablePartitionLevelCircuitBreaker) {\n this.dispose();\n return;\n }\n\n for (const pkRange of this.partitionKeyRangeToLocationForReadAndWrite.keys()) {\n const partitionFailover = this.partitionKeyRangeToLocationForReadAndWrite.get(pkRange);\n if (!partitionFailover) continue;\n\n const { firstRequestFailureTime } =\n await partitionFailover.snapshotPartitionFailoverTimestamps();\n const now = new Date();\n\n if (\n now.getTime() - firstRequestFailureTime >\n Constants.AllowedPartitionUnavailabilityDurationInMs\n ) {\n // Un-deterministically marking the original failed endpoint for the PkRange back to healthy.\n // Initiate Failback to the original failed location.\n this.partitionKeyRangeToLocationForReadAndWrite.delete(pkRange);\n }\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"globalPartitionEndpointManager.js","sourceRoot":"","sources":["../../src/globalPartitionEndpointManager.ts"],"names":[],"mappings":";;;AAAA,uCAAuC;AACvC,kCAAkC;AAClC,gDAA+E;AAC/E,yCAMoB;AACpB,yFAAmF;AACnF,qDAAwD;AACxD,6CAAsD;AACtD,yDAA2D;AAE3D;;;GAGG;AACH,MAAa,8BAA8B;IAe/B;IAdO,mCAAmC,CAA6C;IAChF,0CAA0C,CAGzD;IACM,kBAAkB,CAAW;IAC9B,uBAAuB,CAAS;IAC/B,yCAAyC,CAAkB;IAEnE;;OAEG;IACH,YACE,OAA4B,EACpB,qBAA4C;QAA5C,0BAAqB,GAArB,qBAAqB,CAAuB;QAEpD,IAAI,CAAC,mCAAmC,GAAG,IAAI,GAAG,EAAyC,CAAC;QAC5F,IAAI,CAAC,0CAA0C,GAAG,IAAI,GAAG,EAGtD,CAAC;QACJ,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC;QACtE,IAAI,CAAC,uBAAuB,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5F,IAAI,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,EAAE,CAAC;YACpD,IAAI,CAAC,kCAAkC,EAAE,CAAC;QAC5C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,yBAAyB,CACpC,cAA8B,EAC9B,cAAsC;QAEtC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,qCAAqC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;YAC9E,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,iDAAiD,GACrD,IAAI,CAAC,iDAAiD,CAAC,cAAc,CAAC,CAAC;QACzE,MAAM,gDAAgD,GACpD,IAAI,CAAC,gDAAgD,CAAC,cAAc,CAAC,CAAC;QAExE,IACE,iDAAiD;YACjD,CAAC,gDAAgD;gBAC/C,CAAC,MAAM,IAAI,CAAC,uCAAuC,CACjD,cAAc,EACd,iDAAiD,EACjD,gDAAgD,CACjD,CAAC,CAAC,EACL,CAAC;YACD,OAAO,IAAI,CAAC,8CAA8C,CACxD,cAAc,EACd,cAAc,EACd,iDAAiD,EACjD,gDAAgD,CACjD,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,oCAAoC,CAC/C,cAA8B,EAC9B,cAAsC;QAEtC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,qCAAqC,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;YAC/E,OAAO,cAAc,CAAC;QACxB,CAAC;QAED,MAAM,mBAAmB,GAAG,cAAc,CAAC,mBAAmB,CAAC;QAE/D,IAAI,IAAI,CAAC,iDAAiD,CAAC,cAAc,CAAC,EAAE,CAAC;YAC3E,IAAI,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBACtE,MAAM,iBAAiB,GAAG,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAC5F,cAAc,CAAC,QAAQ,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,CAAC;gBACjE,cAAc,CAAC,wBAAwB,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;gBACjE,OAAO,cAAc,CAAC;YACxB,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,gDAAgD,CAAC,cAAc,CAAC,EAAE,CAAC;YACjF,IAAI,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC7E,MAAM,iBAAiB,GACrB,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;gBAE3E,MAAM,yCAAyC,GAC7C,MAAM,iBAAiB,CAAC,yCAAyC,CAC/D,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC,CAC5C,CAAC;gBACJ,IAAI,yCAAyC,EAAE,CAAC;oBAC9C,cAAc,CAAC,QAAQ,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,CAAC;oBACjE,cAAc,CAAC,wBAAwB,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;oBACjE,OAAO,cAAc,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;;OAGG;IACI,OAAO;QACZ,IAAI,IAAI,CAAC,yCAAyC,EAAE,CAAC;YACnD,YAAY,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;YAC7D,IAAI,CAAC,yCAAyC,GAAG,SAAS,CAAC;QAC7D,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,8CAA8C,CAC1D,cAA8B,EAC9B,cAAsC,EACtC,iDAA0D,EAC1D,gDAAyD;QAEzD,MAAM,mBAAmB,GAAG,cAAc,CAAC,mBAAmB,CAAC;QAC/D,MAAM,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC;QAE/C,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QAC1E,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,IAAI,iDAAiD,EAAE,CAAC;YACtD,kIAAkI;YAClI,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;gBACrC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,IAAI,CAAC,wDAAwD,CAClE,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,IAAI,CAAC,mCAAmC,EACxC,cAAc,CACf,CAAC;QACJ,CAAC;aAAM,IAAI,gDAAgD,EAAE,CAAC;YAC5D,wHAAwH;YACxH,iHAAiH;YACjH,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAClE,KAAK,MAAM,iBAAiB,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;oBACxD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CACjC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAA,+BAAiB,EAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAA,+BAAiB,EAAC,iBAAiB,CAAC,CAC9E,CAAC;oBACF,IAAI,QAAQ,EAAE,CAAC;wBACb,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;oBACvD,CAAC;gBACH,CAAC;gBAED,kDAAkD;gBAClD,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;oBACrC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,CAAC;wBAC9D,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;oBACvD,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;oBACrC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YACD,OAAO,IAAI,CAAC,wDAAwD,CAClE,mBAAmB,EACnB,cAAc,EACd,aAAa,EACb,IAAI,CAAC,0CAA0C,EAC/C,cAAc,CACf,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,uCAAuC,CACnD,cAA8B,EAC9B,iDAA0D,EAC1D,gDAAyD;QAEzD,MAAM,mBAAmB,GAAG,cAAc,CAAC,mBAAmB,CAAC;QAC/D,MAAM,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC;QAC/C,IAAI,6BAA4D,CAAC;QAEjE,IAAI,iDAAiD,EAAE,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBACvE,+DAA+D;gBAC/D,MAAM,YAAY,GAAG,IAAI,gEAA6B,CAAC,cAAc,CAAC,CAAC;gBACvE,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;YAClF,CAAC;YACD,6BAA6B;gBAC3B,IAAI,CAAC,mCAAmC,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACtE,CAAC;aAAM,IAAI,gDAAgD,EAAE,CAAC;YAC5D,IAAI,CAAC,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;gBAC9E,+DAA+D;gBAC/D,MAAM,YAAY,GAAG,IAAI,gEAA6B,CAAC,cAAc,CAAC,CAAC;gBACvE,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;YACzF,CAAC;YACD,6BAA6B;gBAC3B,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAA,kCAAkB,EAChB,6BAA6B,EAC7B,yEAAyE,CAC1E,CAAC;QAEF,MAAM,yBAAyB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7C,MAAM,6BAA6B,CAAC,6BAA6B,CAC/D,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC,EAC3C,yBAAyB,CAC1B,CAAC;QAEF,OAAO,6BAA6B,CAAC,yCAAyC,CAC5E,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC,CAC5C,CAAC;IACJ,CAAC;IAED,yEAAyE;IACjE,KAAK,CAAC,qCAAqC,CACjD,cAA8B,EAC9B,4BAAqC;QAErC,IACE,CAAC,cAAc;YACf,CAAC,cAAc,CAAC,aAAa;YAC7B,CAAC,cAAc,CAAC,YAAY;YAC5B,CAAC,cAAc,CAAC,mBAAmB,EACnC,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,qCAAqC,GAAG,MAAM,IAAI,CAAC,qCAAqC,CAC5F,cAAc,CAAC,aAAa,EAC5B,cAAc,CAAC,YAAY,CAC5B,CAAC;QACF,IAAI,CAAC,qCAAqC,EAAE,CAAC;YAC3C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,4BAA4B,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,0FAA0F;IAClF,KAAK,CAAC,qCAAqC,CACjD,aAA6B,EAC7B,YAA2B;QAE3B,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,gBAAgB,EAAE,CAAC;QAC1E,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC9B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IACE,YAAY,KAAK,uBAAY,CAAC,IAAI;YAClC,CAAC,YAAY,KAAK,uBAAY,CAAC,KAAK,IAAI,aAAa,KAAK,wBAAa,CAAC,OAAO,CAAC,EAChF,CAAC;YACD,qHAAqH;YACrH,yGAAyG;YACzG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;OAIG;IACK,iDAAiD,CACvD,cAA8B;QAE9B,OAAO,CACL,IAAI,CAAC,wCAAwC,EAAE;YAC/C,CAAC,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC;YAC5C,CAAC,IAAI,CAAC,qBAAqB,CAAC,4BAA4B,CACtD,cAAc,CAAC,YAAY,EAC3B,cAAc,CAAC,aAAa,CAC7B,CACF,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,gDAAgD,CACtD,cAA8B;QAE9B,MAAM,kCAAkC,GAAG,IAAI,CAAC,qCAAqC,EAAE,CAAC;QACxF,IAAI,CAAC,kCAAkC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC,qBAAqB,CAAC,4BAA4B,CAC5D,cAAc,CAAC,YAAY,EAC3B,cAAc,CAAC,aAAa,CAC7B,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,KAAK,CAAC,wDAAwD,CACpE,mBAA2B,EAC3B,cAAsB,EACtB,aAAgC,EAChC,2BAAuE,EACvE,cAAsC;QAEtC,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC1D,+DAA+D;YAC/D,MAAM,YAAY,GAAG,IAAI,gEAA6B,CAAC,cAAc,CAAC,CAAC;YACvE,2BAA2B,CAAC,GAAG,CAAC,mBAAmB,EAAE,YAAY,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,iBAAiB,GAAG,2BAA2B,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAE/E,4DAA4D;QAC5D,IACE,MAAM,iBAAiB,CAAC,mBAAmB,CACzC,aAAa,EACb,cAAc,EACd,cAAc,EACd,mBAAmB,CACpB,EACD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,qEAAqE;QACrE,2BAA2B,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;;;OAQG;IACK,kCAAkC;QACxC,IAAI,CAAC,yCAAyC,GAAG,IAAA,6BAAmB,EAAC,KAAK,IAAI,EAAE;YAC9E,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,8CAA8C,EAAE,CAAC;YAC9D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,oDAAoD,EAAE,GAAG,CAAC,CAAC;YAC3E,CAAC;QACH,CAAC,EAAE,oBAAS,CAAC,+CAA+C,CAAC,CAAC;IAChE,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,8CAA8C;QAC1D,oFAAoF;QAEpF,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,0CAA0C,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7E,MAAM,iBAAiB,GAAG,IAAI,CAAC,0CAA0C,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACvF,IAAI,CAAC,iBAAiB;gBAAE,SAAS;YAEjC,MAAM,EAAE,uBAAuB,EAAE,GAC/B,MAAM,iBAAiB,CAAC,mCAAmC,EAAE,CAAC;YAChE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YAEvB,IACE,GAAG,CAAC,OAAO,EAAE,GAAG,uBAAuB;gBACvC,oBAAS,CAAC,0CAA0C,EACpD,CAAC;gBACD,6FAA6F;gBAC7F,qDAAqD;gBACrD,IAAI,CAAC,0CAA0C,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAClE,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACI,gCAAgC,CAAC,SAAkB;QACxD,4EAA4E;QAC5E,IAAI,SAAS,EAAE,CAAC;YACd,gEAAgE;YAChE,IAAI,CAAC,IAAI,CAAC,yCAAyC,EAAE,CAAC;gBACpD,IAAI,CAAC,kCAAkC,EAAE,CAAC;YAC5C,CAAC;QACH,CAAC;aAAM,CAAC;YACN,oCAAoC;YACpC,IAAI,IAAI,CAAC,yCAAyC,EAAE,CAAC;gBACnD,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;IACH,CAAC;IACD;;;OAGG;IACI,wCAAwC;QAC7C,OAAO,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,CAAC;IACzD,CAAC;IACD;;;OAGG;IACI,qCAAqC;QAC1C,OAAO,IAAI,CAAC,qBAAqB,CAAC,oBAAoB,CAAC;IACzD,CAAC;CACF;AA3aD,wEA2aC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport { OperationType, ResourceType, isReadRequest } from \"./common/index.js\";\nimport {\n Constants,\n DiagnosticNodeInternal,\n type CosmosClientOptions,\n type GlobalEndpointManager,\n type RequestContext,\n} from \"./index.js\";\nimport { PartitionKeyRangeFailoverInfo } from \"./PartitionKeyRangeFailoverInfo.js\";\nimport { normalizeEndpoint } from \"./utils/checkURL.js\";\nimport { startBackgroundTask } from \"./utils/time.js\";\nimport { assertNotUndefined } from \"./utils/typeChecks.js\";\n\n/**\n * @hidden\n * This class is used to failover single partitions to different regions.\n */\nexport class GlobalPartitionEndpointManager {\n private readonly partitionKeyRangeToLocationForWrite: Map<string, PartitionKeyRangeFailoverInfo>;\n private readonly partitionKeyRangeToLocationForReadAndWrite: Map<\n string,\n PartitionKeyRangeFailoverInfo\n >;\n private preferredLocations: string[];\n public preferredLocationsCount: number;\n private circuitBreakerFailbackBackgroundRefresher?: NodeJS.Timeout;\n\n /**\n * @internal\n */\n constructor(\n options: CosmosClientOptions,\n private globalEndpointManager: GlobalEndpointManager,\n ) {\n this.partitionKeyRangeToLocationForWrite = new Map<string, PartitionKeyRangeFailoverInfo>();\n this.partitionKeyRangeToLocationForReadAndWrite = new Map<\n string,\n PartitionKeyRangeFailoverInfo\n >();\n this.preferredLocations = options.connectionPolicy.preferredLocations;\n this.preferredLocationsCount = this.preferredLocations ? this.preferredLocations.length : 0;\n if (this.globalEndpointManager.lastKnownPPCBEnabled) {\n this.initiateCircuitBreakerFailbackLoop();\n }\n }\n\n /**\n * Checks eligibility of the request for partition failover and\n * tries to mark the endpoint unavailable for the partition key range. Future\n * requests will be routed to the next location if available.\n */\n public async tryPartitionLevelFailover(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<boolean> {\n if (!(await this.isRequestEligibleForPartitionFailover(requestContext, true))) {\n return false;\n }\n\n const isRequestEligibleForPerPartitionAutomaticFailover =\n this.isRequestEligibleForPerPartitionAutomaticFailover(requestContext);\n const isRequestEligibleForPartitionLevelCircuitBreaker =\n this.isRequestEligibleForPartitionLevelCircuitBreaker(requestContext);\n\n if (\n isRequestEligibleForPerPartitionAutomaticFailover ||\n (isRequestEligibleForPartitionLevelCircuitBreaker &&\n (await this.incrementFailureCounterAndCheckFailover(\n requestContext,\n isRequestEligibleForPerPartitionAutomaticFailover,\n isRequestEligibleForPartitionLevelCircuitBreaker,\n )))\n ) {\n return this.tryMarkEndpointUnavailableForPartitionKeyRange(\n requestContext,\n diagnosticNode,\n isRequestEligibleForPerPartitionAutomaticFailover,\n isRequestEligibleForPartitionLevelCircuitBreaker,\n );\n }\n return false;\n }\n\n /**\n * Updates the DocumentServiceRequest routing location to point\n * new a location based if a partition level failover occurred.\n */\n public async tryAddPartitionLevelLocationOverride(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<RequestContext> {\n if (!(await this.isRequestEligibleForPartitionFailover(requestContext, false))) {\n return requestContext;\n }\n\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n\n if (this.isRequestEligibleForPerPartitionAutomaticFailover(requestContext)) {\n if (this.partitionKeyRangeToLocationForWrite.has(partitionKeyRangeId)) {\n const partitionFailOver = this.partitionKeyRangeToLocationForWrite.get(partitionKeyRangeId);\n requestContext.endpoint = partitionFailOver.getCurrentEndPoint();\n diagnosticNode.recordEndpointResolution(requestContext.endpoint);\n return requestContext;\n }\n } else if (this.isRequestEligibleForPartitionLevelCircuitBreaker(requestContext)) {\n if (this.partitionKeyRangeToLocationForReadAndWrite.has(partitionKeyRangeId)) {\n const partitionFailOver =\n this.partitionKeyRangeToLocationForReadAndWrite.get(partitionKeyRangeId);\n\n const canCircuitBreakerTriggerPartitionFailOver =\n await partitionFailOver.canCircuitBreakerTriggerPartitionFailOver(\n isReadRequest(requestContext.operationType),\n );\n if (canCircuitBreakerTriggerPartitionFailOver) {\n requestContext.endpoint = partitionFailOver.getCurrentEndPoint();\n diagnosticNode.recordEndpointResolution(requestContext.endpoint);\n return requestContext;\n }\n }\n }\n return requestContext;\n }\n\n /**\n * This method clears the background refresher for circuit breaker failback\n * and stops the periodic checks for unhealthy endpoints.\n */\n public dispose(): void {\n if (this.circuitBreakerFailbackBackgroundRefresher) {\n clearTimeout(this.circuitBreakerFailbackBackgroundRefresher);\n this.circuitBreakerFailbackBackgroundRefresher = undefined;\n }\n }\n\n private async tryMarkEndpointUnavailableForPartitionKeyRange(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n isRequestEligibleForPerPartitionAutomaticFailover: boolean,\n isRequestEligibleForPartitionLevelCircuitBreaker: boolean,\n ): Promise<boolean> {\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n const failedEndPoint = requestContext.endpoint;\n\n const readLocations = await this.globalEndpointManager.getReadLocations();\n const readEndPoints: string[] = [];\n\n if (isRequestEligibleForPerPartitionAutomaticFailover) {\n // For any single master write accounts, the next locations to fail over will be the read regions configured at the account level.\n for (const location of readLocations) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n return this.tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId,\n failedEndPoint,\n readEndPoints,\n this.partitionKeyRangeToLocationForWrite,\n diagnosticNode,\n );\n } else if (isRequestEligibleForPartitionLevelCircuitBreaker) {\n // For the read requests or multi-master write requests, the next locations to fail over will be the preferred locations\n // configured at the account level plus any other read locations that are not already in the preferred locations.\n if (this.preferredLocations && this.preferredLocations.length > 0) {\n for (const preferredLocation of this.preferredLocations) {\n const location = readLocations.find(\n (loc) => normalizeEndpoint(loc.name) === normalizeEndpoint(preferredLocation),\n );\n if (location) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n\n // Add the rest of the locations not already added\n for (const location of readLocations) {\n if (!readEndPoints.includes(location.databaseAccountEndpoint)) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n } else {\n for (const location of readLocations) {\n readEndPoints.push(location.databaseAccountEndpoint);\n }\n }\n return this.tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId,\n failedEndPoint,\n readEndPoints,\n this.partitionKeyRangeToLocationForReadAndWrite,\n diagnosticNode,\n );\n }\n return false;\n }\n\n /**\n * Increments the failure counter for the specified partition and checks if the partition can fail over.\n * This method is used to determine if a partition should be failed over based on the number of request failures.\n */\n private async incrementFailureCounterAndCheckFailover(\n requestContext: RequestContext,\n isRequestEligibleForPerPartitionAutomaticFailover: boolean,\n isRequestEligibleForPartitionLevelCircuitBreaker: boolean,\n ): Promise<boolean> {\n const partitionKeyRangeId = requestContext.partitionKeyRangeId;\n const failedEndPoint = requestContext.endpoint;\n let partitionKeyRangeFailoverInfo: PartitionKeyRangeFailoverInfo;\n\n if (isRequestEligibleForPerPartitionAutomaticFailover) {\n if (!this.partitionKeyRangeToLocationForWrite.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n this.partitionKeyRangeToLocationForWrite.set(partitionKeyRangeId, failoverInfo);\n }\n partitionKeyRangeFailoverInfo =\n this.partitionKeyRangeToLocationForWrite.get(partitionKeyRangeId);\n } else if (isRequestEligibleForPartitionLevelCircuitBreaker) {\n if (!this.partitionKeyRangeToLocationForReadAndWrite.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n this.partitionKeyRangeToLocationForReadAndWrite.set(partitionKeyRangeId, failoverInfo);\n }\n partitionKeyRangeFailoverInfo =\n this.partitionKeyRangeToLocationForReadAndWrite.get(partitionKeyRangeId);\n } else {\n return false;\n }\n\n assertNotUndefined(\n partitionKeyRangeFailoverInfo,\n \"partitionKeyRangeFailoverInfo should be set if failover flags are true.\",\n );\n\n const currentTimeInMilliseconds = Date.now();\n await partitionKeyRangeFailoverInfo.incrementRequestFailureCounts(\n isReadRequest(requestContext.operationType),\n currentTimeInMilliseconds,\n );\n\n return partitionKeyRangeFailoverInfo.canCircuitBreakerTriggerPartitionFailOver(\n isReadRequest(requestContext.operationType),\n );\n }\n\n /** Validates if the given request is eligible for partition failover. */\n private async isRequestEligibleForPartitionFailover(\n requestContext: RequestContext,\n shouldValidateFailedLocation: boolean,\n ): Promise<boolean> {\n if (\n !requestContext ||\n !requestContext.operationType ||\n !requestContext.resourceType ||\n !requestContext.partitionKeyRangeId\n ) {\n return false;\n }\n\n const canUsePartitionLevelFailoverLocations = await this.canUsePartitionLevelFailoverLocations(\n requestContext.operationType,\n requestContext.resourceType,\n );\n if (!canUsePartitionLevelFailoverLocations) {\n return false;\n }\n\n if (shouldValidateFailedLocation && !requestContext.endpoint) {\n return false;\n }\n return true;\n }\n\n /** Determines if partition level failover locations can be used for the given request. */\n private async canUsePartitionLevelFailoverLocations(\n operationType?: OperationType,\n resourceType?: ResourceType,\n ): Promise<boolean> {\n const readEndPoints = await this.globalEndpointManager.getReadEndpoints();\n if (readEndPoints.length <= 1) {\n return false;\n }\n if (\n resourceType === ResourceType.item ||\n (resourceType === ResourceType.sproc && operationType === OperationType.Execute)\n ) {\n // Right now, for single-master only reads are supported for circuit breaker, and writes are supported for automatic.\n // failover. For multi master, both reads and writes are supported. Hence return true for both the cases.\n return true;\n }\n return false;\n }\n\n /**\n * Determines if a request is eligible for per-partition automatic failover.\n * A request is eligible if it is a write request, partition level failover is enabled,\n * and the global endpoint manager cannot use multiple write locations for the request.\n */\n private isRequestEligibleForPerPartitionAutomaticFailover(\n requestContext: RequestContext,\n ): boolean {\n return (\n this.isPartitionLevelAutomaticFailoverEnabled() &&\n !isReadRequest(requestContext.operationType) &&\n !this.globalEndpointManager.canUseMultipleWriteLocations(\n requestContext.resourceType,\n requestContext.operationType,\n )\n );\n }\n\n /**\n * Determines if a request is eligible for partition-level circuit breaker.\n * This method checks if partition-level circuit breaker is enabled, and if the request is a read-only request or\n * the global endpoint manager can use multiple write locations for the request.\n */\n private isRequestEligibleForPartitionLevelCircuitBreaker(\n requestContext: RequestContext,\n ): boolean {\n const enablePartitionLevelCircuitBreaker = this.isPartitionLevelCircuitBreakerEnabled();\n if (!enablePartitionLevelCircuitBreaker) {\n return false;\n }\n if (isReadRequest(requestContext.operationType)) {\n return true;\n }\n return this.globalEndpointManager.canUseMultipleWriteLocations(\n requestContext.resourceType,\n requestContext.operationType,\n );\n }\n\n /**\n * Attempts to add or update the partition failover information and move to the next available location.\n * This method checks if the current location for the partition key range has failed and updates the failover\n * information to route the request to the next available location. If all locations have been tried, it removes\n * the failover information for the partition key range. Return True if the failover information was successfully\n * updated and the request was routed to a new location, otherwise false.\n */\n private async tryAddOrUpdatePartitionFailoverInfoAndMoveToNextLocation(\n partitionKeyRangeId: string,\n failedEndPoint: string,\n nextEndPoints: readonly string[],\n partitionKeyRangeToLocation: Map<string, PartitionKeyRangeFailoverInfo>,\n diagnosticNode: DiagnosticNodeInternal,\n ): Promise<boolean> {\n if (!partitionKeyRangeToLocation.has(partitionKeyRangeId)) {\n // If the partition key range is not already in the map, add it\n const failoverInfo = new PartitionKeyRangeFailoverInfo(failedEndPoint);\n partitionKeyRangeToLocation.set(partitionKeyRangeId, failoverInfo);\n }\n const partitionFailOver = partitionKeyRangeToLocation.get(partitionKeyRangeId);\n\n // Will return true if it was able to update to a new region\n if (\n await partitionFailOver.tryMoveNextLocation(\n nextEndPoints,\n failedEndPoint,\n diagnosticNode,\n partitionKeyRangeId,\n )\n ) {\n return true;\n }\n // All the locations have been tried. Remove the override information\n partitionKeyRangeToLocation.delete(partitionKeyRangeId);\n return false;\n }\n\n /**\n * Initiates a background loop that periodically checks for unhealthy endpoints\n * and attempts to open connections to them. If a connection is successfully\n * established, it initiates a failback to the original location for the partition key range.\n * This is useful for scenarios where a partition key range has been marked as unavailable\n * due to a circuit breaker, and we want to periodically check if the original location\n * has become healthy again.\n * The loop runs at a defined interval specified by Constants.StalePartitionUnavailabilityRefreshIntervalInMs.\n */\n private initiateCircuitBreakerFailbackLoop(): void {\n this.circuitBreakerFailbackBackgroundRefresher = startBackgroundTask(async () => {\n try {\n await this.openConnectionToUnhealthyEndpointsWithFailback();\n } catch (err) {\n console.error(\"Failed to open connection to unhealthy endpoints: \", err);\n }\n }, Constants.StalePartitionUnavailabilityRefreshIntervalInMs);\n }\n\n /**\n * Attempts to open connections to unhealthy endpoints and initiates failback if the connections are successful.\n * This method checks the partition key ranges that have failed locations and tries to re-establish connections\n * to those locations. If a connection is successfully re-established, it initiates a failback to the original\n * location for the partition key range.\n */\n private async openConnectionToUnhealthyEndpointsWithFailback(): Promise<void> {\n // If partition level circuit breaker or failover is not enabled, dispose the timer.\n\n for (const pkRange of this.partitionKeyRangeToLocationForReadAndWrite.keys()) {\n const partitionFailover = this.partitionKeyRangeToLocationForReadAndWrite.get(pkRange);\n if (!partitionFailover) continue;\n\n const { firstRequestFailureTime } =\n await partitionFailover.snapshotPartitionFailoverTimestamps();\n const now = new Date();\n\n if (\n now.getTime() - firstRequestFailureTime >\n Constants.AllowedPartitionUnavailabilityDurationInMs\n ) {\n // Un-deterministically marking the original failed endpoint for the PkRange back to healthy.\n // Initiate Failback to the original failed location.\n this.partitionKeyRangeToLocationForReadAndWrite.delete(pkRange);\n }\n }\n }\n\n /**\n * @internal\n */\n public changeCircuitBreakerFailbackLoop(isEnabled: boolean): void {\n // Start or stop the circuit breaker failback loop based on PPAF/PPCB status\n if (isEnabled) {\n // Only start if not already running to prevent duplicate timers\n if (!this.circuitBreakerFailbackBackgroundRefresher) {\n this.initiateCircuitBreakerFailbackLoop();\n }\n } else {\n // Only dispose if currently running\n if (this.circuitBreakerFailbackBackgroundRefresher) {\n this.dispose();\n }\n }\n }\n /**\n * Gets a value indicating whether per-partition automatic failover is currently enabled.\n * @internal\n */\n public isPartitionLevelAutomaticFailoverEnabled(): boolean {\n return this.globalEndpointManager.lastKnownPPAFEnabled;\n }\n /**\n * Gets a value indicating whether per-partition automatic failover is currently enabled.\n * @internal\n */\n public isPartitionLevelCircuitBreakerEnabled(): boolean {\n return this.globalEndpointManager.lastKnownPPCBEnabled;\n }\n}\n"]}
|
|
@@ -44,8 +44,8 @@ async function httpRequest(requestContext, diagnosticNode) {
|
|
|
44
44
|
// If the request is a read request and partition level failover or circuit breaker is enabled,
|
|
45
45
|
// set a shorter timeout to allow for quicker failover in case of partition unavailability.
|
|
46
46
|
// This is to ensure that read requests can quickly failover to another partition if the current one is unavailable.
|
|
47
|
-
if ((requestContext.
|
|
48
|
-
requestContext.
|
|
47
|
+
if ((requestContext.globalPartitionEndpointManager?.isPartitionLevelAutomaticFailoverEnabled() ||
|
|
48
|
+
requestContext.globalPartitionEndpointManager?.isPartitionLevelCircuitBreakerEnabled()) &&
|
|
49
49
|
requestContext.partitionKeyRangeId &&
|
|
50
50
|
requestContext.resourceType === constants_js_1.ResourceType.item &&
|
|
51
51
|
(0, index_js_1.isReadRequest)(requestContext.operationType)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestHandler.js","sourceRoot":"","sources":["../../../src/request/RequestHandler.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;;AAGlC,kEAAqF;AACrF,iDAA+D;AAC/D,yDAAiE;AACjE,oDAAgE;AAChE,+EAAyD;AACzD,uDAAwE;AACxE,yDAAmD;AACnD,6CAA4C;AAG5C,uDAAiD;AACjD,8DAAsE;AAEtE,0CAAmD;AAEnD,wFAA8E;AAC9E,4DAA6D;AAC7D,8CAA2D;AAE3D,MAAM,MAAM,GAAgB,IAAA,2BAAkB,EAAC,gBAAgB,CAAC,CAAC;AAEjE,KAAK,UAAU,cAAc,CAC3B,cAAsC,EACtC,cAA8B;IAE9B,OAAO,IAAA,0BAAc,EAAC,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,oBAAQ,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,WAAW,CACxB,cAA8B,EAC9B,cAAsC;IAOtC,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;IAEjC,mEAAmE;IACnE,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,WAAW,CAAC;IAChF,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,UAAU,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACxC,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,IAAI,cAAc,GAAG,cAAc,CAAC,gBAAgB,CAAC,cAAc,CAAC;IACpE,+FAA+F;IAC/F,2FAA2F;IAC3F,oHAAoH;IACpH,IACE,CAAC,cAAc,CAAC,qBAAqB,CAAC,4BAA4B;QAChE,cAAc,CAAC,qBAAqB,CAAC,kCAAkC,CAAC;QAC1E,cAAc,CAAC,mBAAmB;QAClC,cAAc,CAAC,YAAY,KAAK,2BAAY,CAAC,IAAI;QACjD,IAAA,wBAAa,EAAC,cAAc,CAAC,aAAa,CAAC,EAC3C,CAAC;QACD,cAAc,GAAG,IAAI,CAAC,GAAG,CACvB,cAAc,CAAC,gBAAgB,CAAC,cAAc,EAC9C,wBAAS,CAAC,0BAA0B,CACrC,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;QAC9B,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,EAAE,cAAc,CAAC,CAAC;IAEnB,IAAI,QAA0B,CAAC;IAE/B,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC;QACxB,cAAc,CAAC,IAAI,GAAG,IAAA,yBAAY,EAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,IAAI,IAAA,4CAA0B,GAAE,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAA,qBAAU,EAAC,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,IAAA,sCAAiB,EAAC,cAAc,CAAC,OAAc,CAAC,CAAC;IACpE,MAAM,eAAe,GAAG,IAAA,0CAAqB,EAAC;QAC5C,GAAG;QACH,OAAO,EAAE,UAAU;QACnB,MAAM,EAAE,cAAc,CAAC,MAAM;QAC7B,WAAW,EAAE,MAAM;QACnB,IAAI,EAAE,cAAc,CAAC,IAAI;KAC1B,CAAC,CAAC;IACH,IAAI,cAAc,CAAC,YAAY,EAAE,CAAC;QAChC,eAAe,CAAC,KAAK,GAAG,cAAc,CAAC,YAAY,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/B,eAAe,CAAC,KAAK,GAAG,SAAS,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,kCAAgB,CAAC,CAAC,CAAC,mCAAiB,CAAC;QAC9F,eAAe,CAAC,uBAAuB,GAAG,SAAS,CAAC,QAAQ,KAAK,OAAO,CAAC;IAC3E,CAAC;IAED,MAAM,gBAAgB,GAAG,IAAA,iCAAuB,GAAE,CAAC;IACnD,IAAI,CAAC;QACH,IAAI,cAAc,CAAC,QAAQ,EAAE,CAAC;YAC5B,QAAQ,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,WAAW,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QACrF,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,uFAAuF;YACvF,IAAI,UAAU,IAAI,UAAU,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;gBAC9C,YAAY,CAAC,OAAO,CAAC,CAAC;gBACtB,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAI,8BAAY,CACpB,yCAAyC,cAAc,CAAC,gBAAgB,CAAC,cAAc,KAAK,CAC7F,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;IAED,YAAY,CAAC,OAAO,CAAC,CAAC;IACtB,MAAM,MAAM,GACV,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,UAAU,KAAK,EAAE;QAC9E,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACtC,MAAM,eAAe,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;IAElD,MAAM,SAAS,GAAG,eAAe,CAAC,wBAAS,CAAC,WAAW,CAAC,SAAS,CAAC;QAChE,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,wBAAS,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAChE,CAAC,CAAC,SAAS,CAAC;IAEd,cAAc,CAAC,2BAA2B,CACxC,gBAAgB,EAChB,cAAc,EACd,QAAQ,EACR,SAAS,EACT,GAAG,CACJ,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAkB,IAAI,gCAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvE,MAAM,CAAC,OAAO,CACZ,QAAQ,CAAC,MAAM;YACb,GAAG;YACH,cAAc,CAAC,QAAQ;YACvB,GAAG;YACH,cAAc,CAAC,IAAI;YACnB,GAAG;YACH,MAAM,CAAC,OAAO,CACjB,CAAC;QAEF,aAAa,CAAC,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC;QACrC,aAAa,CAAC,IAAI,GAAG,MAAM,CAAC;QAC5B,aAAa,CAAC,OAAO,GAAG,eAAe,CAAC;QAExC,IAAI,wBAAS,CAAC,WAAW,CAAC,UAAU,IAAI,eAAe,EAAE,CAAC;YACxD,aAAa,CAAC,UAAU,GAAG,eAAe,CAAC,wBAAS,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,wBAAS,CAAC,WAAW,CAAC,SAAS,IAAI,eAAe,EAAE,CAAC;YACvD,aAAa,CAAC,SAAS,GAAG,SAAS,CAAC;QACtC,CAAC;QAED,IAAI,wBAAS,CAAC,WAAW,CAAC,cAAc,IAAI,eAAe,EAAE,CAAC;YAC5D,aAAa,CAAC,cAAc,GAAG,QAAQ,CACrC,eAAe,CAAC,wBAAS,CAAC,WAAW,CAAC,cAAc,CAAC,EACrD,EAAE,CACH,CAAC;YACF,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,0BAA0B,EAAE;gBAC/D,GAAG,EAAE,GAAG,EAAE;oBACR,OAAO,aAAa,CAAC,cAAc,CAAC;gBACtC,CAAC;aACF,CAAC,CAAC;QACL,CAAC;QAED,MAAM,aAAa,CAAC;IACtB,CAAC;IACD,OAAO;QACL,OAAO,EAAE,eAAe;QACxB,MAAM;QACN,IAAI,EAAE,QAAQ,CAAC,MAAM;QACrB,SAAS;KACV,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,OAAO,CACpB,cAA8B,EAC9B,cAAsC;IAEtC,IAAI,cAAc,CAAC,IAAI,EAAE,CAAC;QACxB,cAAc,CAAC,IAAI,GAAG,IAAA,yBAAY,EAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,OAAO,IAAA,mCAAkB,EACvB,KAAK,EAAE,SAAiC,EAAE,EAAE;QAC1C,OAAO,YAAY,CAAC,OAAO,CAAC;YAC1B,cAAc,EAAE,SAAS;YACzB,cAAc;YACd,cAAc;SACf,CAAC,CAAC;IACL,CAAC,EACD,cAAc,EACd,8CAAkB,CAAC,gBAAgB,CACpC,CAAC;AACJ,CAAC;AAEY,QAAA,cAAc,GAAG;IAC5B,OAAO;CACR,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PipelineResponse } from \"@azure/core-rest-pipeline\";\nimport { createPipelineRequest, createHttpHeaders } from \"@azure/core-rest-pipeline\";\nimport { isReadRequest, prepareURL } from \"../common/index.js\";\nimport { Constants, ResourceType } from \"../common/constants.js\";\nimport { executePlugins, PluginOn } from \"../plugins/Plugin.js\";\nimport * as RetryUtility from \"../retry/retryUtility.js\";\nimport { defaultHttpAgent, defaultHttpsAgent } from \"./defaultAgent.js\";\nimport { ErrorResponse } from \"./ErrorResponse.js\";\nimport { bodyFromData } from \"./request.js\";\nimport type { RequestContext } from \"./RequestContext.js\";\nimport type { Response as CosmosResponse } from \"./Response.js\";\nimport { TimeoutError } from \"./TimeoutError.js\";\nimport { getCachedDefaultHttpClient } from \"../utils/cachedClient.js\";\nimport type { AzureLogger } from \"@azure/logger\";\nimport { createClientLogger } from \"@azure/logger\";\nimport type { DiagnosticNodeInternal } from \"../diagnostics/DiagnosticNodeInternal.js\";\nimport { DiagnosticNodeType } from \"../diagnostics/DiagnosticNodeInternal.js\";\nimport { addDiagnosticChild } from \"../utils/diagnostics.js\";\nimport { getCurrentTimestampInMs } from \"../utils/time.js\";\n\nconst logger: AzureLogger = createClientLogger(\"RequestHandler\");\n\nasync function executeRequest(\n diagnosticNode: DiagnosticNodeInternal,\n requestContext: RequestContext,\n): Promise<CosmosResponse<any>> {\n return executePlugins(diagnosticNode, requestContext, httpRequest, PluginOn.request);\n}\n\n/**\n * @hidden\n */\nasync function httpRequest(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n): Promise<{\n headers: any;\n result: any;\n code: number;\n substatus: number;\n}> {\n const controller = new AbortController();\n const signal = controller.signal;\n\n // Wrap users passed abort events and call our own internal abort()\n const userSignal = requestContext.options && requestContext.options.abortSignal;\n if (userSignal) {\n if (userSignal.aborted) {\n controller.abort();\n } else {\n userSignal.addEventListener(\"abort\", () => {\n controller.abort();\n });\n }\n }\n\n let requestTimeout = requestContext.connectionPolicy.requestTimeout;\n // If the request is a read request and partition level failover or circuit breaker is enabled,\n // set a shorter timeout to allow for quicker failover in case of partition unavailability.\n // This is to ensure that read requests can quickly failover to another partition if the current one is unavailable.\n if (\n (requestContext.globalEndpointManager.enablePartitionLevelFailover ||\n requestContext.globalEndpointManager.enablePartitionLevelCircuitBreaker) &&\n requestContext.partitionKeyRangeId &&\n requestContext.resourceType === ResourceType.item &&\n isReadRequest(requestContext.operationType)\n ) {\n requestTimeout = Math.min(\n requestContext.connectionPolicy.requestTimeout,\n Constants.RequestTimeoutForReadsInMs,\n );\n }\n const timeout = setTimeout(() => {\n controller.abort();\n }, requestTimeout);\n\n let response: PipelineResponse;\n\n if (requestContext.body) {\n requestContext.body = bodyFromData(requestContext.body);\n }\n\n const httpsClient = requestContext.httpClient ?? getCachedDefaultHttpClient();\n const url = prepareURL(requestContext.endpoint, requestContext.path);\n const reqHeaders = createHttpHeaders(requestContext.headers as any);\n const pipelineRequest = createPipelineRequest({\n url,\n headers: reqHeaders,\n method: requestContext.method,\n abortSignal: signal,\n body: requestContext.body,\n });\n if (requestContext.requestAgent) {\n pipelineRequest.agent = requestContext.requestAgent;\n } else {\n const parsedUrl = new URL(url);\n pipelineRequest.agent = parsedUrl.protocol === \"http:\" ? defaultHttpAgent : defaultHttpsAgent;\n pipelineRequest.allowInsecureConnection = parsedUrl.protocol === \"http:\";\n }\n\n const startTimeUTCInMs = getCurrentTimestampInMs();\n try {\n if (requestContext.pipeline) {\n response = await requestContext.pipeline.sendRequest(httpsClient, pipelineRequest);\n } else {\n response = await httpsClient.sendRequest(pipelineRequest);\n }\n } catch (error: any) {\n if (error.name === \"AbortError\") {\n // If the user passed signal caused the abort, cancel the timeout and rethrow the error\n if (userSignal && userSignal.aborted === true) {\n clearTimeout(timeout);\n throw error;\n }\n throw new TimeoutError(\n `Timeout Error! Request took more than ${requestContext.connectionPolicy.requestTimeout} ms`,\n );\n }\n throw error;\n }\n\n clearTimeout(timeout);\n const result =\n response.status === 204 || response.status === 304 || response.bodyAsText === \"\"\n ? null\n : JSON.parse(response.bodyAsText);\n const responseHeaders = response.headers.toJSON();\n\n const substatus = responseHeaders[Constants.HttpHeaders.SubStatus]\n ? parseInt(responseHeaders[Constants.HttpHeaders.SubStatus], 10)\n : undefined;\n\n diagnosticNode.recordSuccessfulNetworkCall(\n startTimeUTCInMs,\n requestContext,\n response,\n substatus,\n url,\n );\n\n if (response.status >= 400) {\n const errorResponse: ErrorResponse = new ErrorResponse(result.message);\n logger.warning(\n response.status +\n \" \" +\n requestContext.endpoint +\n \" \" +\n requestContext.path +\n \" \" +\n result.message,\n );\n\n errorResponse.code = response.status;\n errorResponse.body = result;\n errorResponse.headers = responseHeaders;\n\n if (Constants.HttpHeaders.ActivityId in responseHeaders) {\n errorResponse.activityId = responseHeaders[Constants.HttpHeaders.ActivityId];\n }\n\n if (Constants.HttpHeaders.SubStatus in responseHeaders) {\n errorResponse.substatus = substatus;\n }\n\n if (Constants.HttpHeaders.RetryAfterInMs in responseHeaders) {\n errorResponse.retryAfterInMs = parseInt(\n responseHeaders[Constants.HttpHeaders.RetryAfterInMs],\n 10,\n );\n Object.defineProperty(errorResponse, \"retryAfterInMilliseconds\", {\n get: () => {\n return errorResponse.retryAfterInMs;\n },\n });\n }\n\n throw errorResponse;\n }\n return {\n headers: responseHeaders,\n result,\n code: response.status,\n substatus,\n };\n}\n\n/**\n * @hidden\n */\nasync function request<T>(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n): Promise<CosmosResponse<T>> {\n if (requestContext.body) {\n requestContext.body = bodyFromData(requestContext.body);\n if (!requestContext.body) {\n throw new Error(\"parameter data must be a javascript object, string, or Buffer\");\n }\n }\n\n return addDiagnosticChild(\n async (childNode: DiagnosticNodeInternal) => {\n return RetryUtility.execute({\n diagnosticNode: childNode,\n requestContext,\n executeRequest,\n });\n },\n diagnosticNode,\n DiagnosticNodeType.REQUEST_ATTEMPTS,\n );\n}\n\nexport const RequestHandler = {\n request,\n};\n"]}
|
|
1
|
+
{"version":3,"file":"RequestHandler.js","sourceRoot":"","sources":["../../../src/request/RequestHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport type { PipelineResponse } from \"@azure/core-rest-pipeline\";\nimport { createPipelineRequest, createHttpHeaders } from \"@azure/core-rest-pipeline\";\nimport { isReadRequest, prepareURL } from \"../common/index.js\";\nimport { Constants, ResourceType } from \"../common/constants.js\";\nimport { executePlugins, PluginOn } from \"../plugins/Plugin.js\";\nimport * as RetryUtility from \"../retry/retryUtility.js\";\nimport { defaultHttpAgent, defaultHttpsAgent } from \"./defaultAgent.js\";\nimport { ErrorResponse } from \"./ErrorResponse.js\";\nimport { bodyFromData } from \"./request.js\";\nimport type { RequestContext } from \"./RequestContext.js\";\nimport type { Response as CosmosResponse } from \"./Response.js\";\nimport { TimeoutError } from \"./TimeoutError.js\";\nimport { getCachedDefaultHttpClient } from \"../utils/cachedClient.js\";\nimport type { AzureLogger } from \"@azure/logger\";\nimport { createClientLogger } from \"@azure/logger\";\nimport type { DiagnosticNodeInternal } from \"../diagnostics/DiagnosticNodeInternal.js\";\nimport { DiagnosticNodeType } from \"../diagnostics/DiagnosticNodeInternal.js\";\nimport { addDiagnosticChild } from \"../utils/diagnostics.js\";\nimport { getCurrentTimestampInMs } from \"../utils/time.js\";\n\nconst logger: AzureLogger = createClientLogger(\"RequestHandler\");\n\nasync function executeRequest(\n diagnosticNode: DiagnosticNodeInternal,\n requestContext: RequestContext,\n): Promise<CosmosResponse<any>> {\n return executePlugins(diagnosticNode, requestContext, httpRequest, PluginOn.request);\n}\n\n/**\n * @hidden\n */\nasync function httpRequest(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n): Promise<{\n headers: any;\n result: any;\n code: number;\n substatus: number;\n}> {\n const controller = new AbortController();\n const signal = controller.signal;\n\n // Wrap users passed abort events and call our own internal abort()\n const userSignal = requestContext.options && requestContext.options.abortSignal;\n if (userSignal) {\n if (userSignal.aborted) {\n controller.abort();\n } else {\n userSignal.addEventListener(\"abort\", () => {\n controller.abort();\n });\n }\n }\n\n let requestTimeout = requestContext.connectionPolicy.requestTimeout;\n // If the request is a read request and partition level failover or circuit breaker is enabled,\n // set a shorter timeout to allow for quicker failover in case of partition unavailability.\n // This is to ensure that read requests can quickly failover to another partition if the current one is unavailable.\n if (\n (requestContext.globalPartitionEndpointManager?.isPartitionLevelAutomaticFailoverEnabled() ||\n requestContext.globalPartitionEndpointManager?.isPartitionLevelCircuitBreakerEnabled()) &&\n requestContext.partitionKeyRangeId &&\n requestContext.resourceType === ResourceType.item &&\n isReadRequest(requestContext.operationType)\n ) {\n requestTimeout = Math.min(\n requestContext.connectionPolicy.requestTimeout,\n Constants.RequestTimeoutForReadsInMs,\n );\n }\n const timeout = setTimeout(() => {\n controller.abort();\n }, requestTimeout);\n\n let response: PipelineResponse;\n\n if (requestContext.body) {\n requestContext.body = bodyFromData(requestContext.body);\n }\n\n const httpsClient = requestContext.httpClient ?? getCachedDefaultHttpClient();\n const url = prepareURL(requestContext.endpoint, requestContext.path);\n const reqHeaders = createHttpHeaders(requestContext.headers as any);\n const pipelineRequest = createPipelineRequest({\n url,\n headers: reqHeaders,\n method: requestContext.method,\n abortSignal: signal,\n body: requestContext.body,\n });\n if (requestContext.requestAgent) {\n pipelineRequest.agent = requestContext.requestAgent;\n } else {\n const parsedUrl = new URL(url);\n pipelineRequest.agent = parsedUrl.protocol === \"http:\" ? defaultHttpAgent : defaultHttpsAgent;\n pipelineRequest.allowInsecureConnection = parsedUrl.protocol === \"http:\";\n }\n\n const startTimeUTCInMs = getCurrentTimestampInMs();\n try {\n if (requestContext.pipeline) {\n response = await requestContext.pipeline.sendRequest(httpsClient, pipelineRequest);\n } else {\n response = await httpsClient.sendRequest(pipelineRequest);\n }\n } catch (error: any) {\n if (error.name === \"AbortError\") {\n // If the user passed signal caused the abort, cancel the timeout and rethrow the error\n if (userSignal && userSignal.aborted === true) {\n clearTimeout(timeout);\n throw error;\n }\n throw new TimeoutError(\n `Timeout Error! Request took more than ${requestContext.connectionPolicy.requestTimeout} ms`,\n );\n }\n throw error;\n }\n\n clearTimeout(timeout);\n const result =\n response.status === 204 || response.status === 304 || response.bodyAsText === \"\"\n ? null\n : JSON.parse(response.bodyAsText);\n const responseHeaders = response.headers.toJSON();\n\n const substatus = responseHeaders[Constants.HttpHeaders.SubStatus]\n ? parseInt(responseHeaders[Constants.HttpHeaders.SubStatus], 10)\n : undefined;\n\n diagnosticNode.recordSuccessfulNetworkCall(\n startTimeUTCInMs,\n requestContext,\n response,\n substatus,\n url,\n );\n\n if (response.status >= 400) {\n const errorResponse: ErrorResponse = new ErrorResponse(result.message);\n logger.warning(\n response.status +\n \" \" +\n requestContext.endpoint +\n \" \" +\n requestContext.path +\n \" \" +\n result.message,\n );\n\n errorResponse.code = response.status;\n errorResponse.body = result;\n errorResponse.headers = responseHeaders;\n\n if (Constants.HttpHeaders.ActivityId in responseHeaders) {\n errorResponse.activityId = responseHeaders[Constants.HttpHeaders.ActivityId];\n }\n\n if (Constants.HttpHeaders.SubStatus in responseHeaders) {\n errorResponse.substatus = substatus;\n }\n\n if (Constants.HttpHeaders.RetryAfterInMs in responseHeaders) {\n errorResponse.retryAfterInMs = parseInt(\n responseHeaders[Constants.HttpHeaders.RetryAfterInMs],\n 10,\n );\n Object.defineProperty(errorResponse, \"retryAfterInMilliseconds\", {\n get: () => {\n return errorResponse.retryAfterInMs;\n },\n });\n }\n\n throw errorResponse;\n }\n return {\n headers: responseHeaders,\n result,\n code: response.status,\n substatus,\n };\n}\n\n/**\n * @hidden\n */\nasync function request<T>(\n requestContext: RequestContext,\n diagnosticNode: DiagnosticNodeInternal,\n): Promise<CosmosResponse<T>> {\n if (requestContext.body) {\n requestContext.body = bodyFromData(requestContext.body);\n if (!requestContext.body) {\n throw new Error(\"parameter data must be a javascript object, string, or Buffer\");\n }\n }\n\n return addDiagnosticChild(\n async (childNode: DiagnosticNodeInternal) => {\n return RetryUtility.execute({\n diagnosticNode: childNode,\n requestContext,\n executeRequest,\n });\n },\n diagnosticNode,\n DiagnosticNodeType.REQUEST_ATTEMPTS,\n );\n}\n\nexport const RequestHandler = {\n request,\n};\n"]}
|
|
@@ -78,7 +78,7 @@ class TimeoutFailoverRetryPolicy {
|
|
|
78
78
|
const readRequest = (0, index_js_1.isReadRequest)(this.operationType);
|
|
79
79
|
if (!canUseMultipleWriteLocations &&
|
|
80
80
|
!readRequest &&
|
|
81
|
-
!this.
|
|
81
|
+
!this.globalPartitionEndpointManager?.isPartitionLevelAutomaticFailoverEnabled()) {
|
|
82
82
|
// Write requests on single master cannot be retried if partition level failover is disabled.
|
|
83
83
|
// This means there are no other regions available to serve the writes.
|
|
84
84
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeoutFailoverRetryPolicy.js","sourceRoot":"","sources":["../../../src/retry/timeoutFailoverRetryPolicy.ts"],"names":[],"mappings":";;;AAGA,6DAAuD;AAEvD,iDAA+D;AAE/D,yDAAmD;AAGnD,gEAA8D;AAK9D;;;;;;GAMG;AACH,MAAa,0BAA0B;IAS3B;IACA;IACA;IACA;IACA;IACA;IACA;IAdF,oBAAoB,GAAG,GAAG,CAAC;IAC3B,+BAA+B,GAAG,CAAC,CAAC;IACrC,cAAc,GAAG,CAAC,CAAC;IACnB,kBAAkB,GAAG,CAAC,CAAC;IACvB,OAAO,CAAM;IACb,gBAAgB,CAAM;IAE7B,YACU,qBAA4C,EAC5C,OAAsB,EACtB,UAAsB,EACtB,YAA0B,EAC1B,aAA4B,EAC5B,uBAAgC,EAChC,8BAA+D;QAN/D,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,YAAO,GAAP,OAAO,CAAe;QACtB,eAAU,GAAV,UAAU,CAAY;QACtB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,kBAAa,GAAb,aAAa,CAAe;QAC5B,4BAAuB,GAAvB,uBAAuB,CAAS;QAChC,mCAA8B,GAA9B,8BAA8B,CAAiC;IACtE,CAAC;IAEJ;;;;OAIG;IACK,6BAA6B;QACnC,MAAM,OAAO,GAAG,wBAAS,CAAC,WAAW,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC;QAC9D,MAAM,WAAW,GAAG,wBAAS,CAAC,WAAW,CAAC,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC;QACtE,IAAI,IAAI,CAAC,UAAU,KAAK,qBAAU,CAAC,GAAG,IAAI,OAAO,IAAI,WAAW,EAAE,CAAC;YACjE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAEM,KAAK,CAAC,WAAW,CACtB,GAAkB,EAClB,cAAsC,EACtC,YAA2B,EAC3B,gBAAyB,EACzB,cAA+B;QAE/B,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,YAAY,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACvC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACf,CAAC;QACD,qCAAqC;QACrC,8DAA8D;QAC9D,IAAI,cAAc,IAAI,IAAI,CAAC,8BAA8B,EAAE,CAAC;YAC1D,MAAM,IAAI,CAAC,8BAA8B,CAAC,yBAAyB,CACjE,cAAc,EACd,cAAc,CACf,CAAC;QACJ,CAAC;QACD,iHAAiH;QACjH,IAAI,GAAG,CAAC,IAAI,KAAK,kCAAgB,IAAI,CAAC,IAAI,CAAC,6BAA6B,EAAE,EAAE,CAAC;YAC3E,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IACE,GAAG,CAAC,IAAI,KAAK,4BAAW,CAAC,kBAAkB;YAC3C,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,+BAA+B,EAC/D,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACzD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,4BAA4B,GAAG,IAAI,CAAC,qBAAqB,CAAC,4BAA4B,CAC1F,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,aAAa,CACnB,CAAC;QACF,MAAM,WAAW,GAAG,IAAA,wBAAa,EAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEtD,IACE,CAAC,4BAA4B;YAC7B,CAAC,WAAW;YACZ,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"timeoutFailoverRetryPolicy.js","sourceRoot":"","sources":["../../../src/retry/timeoutFailoverRetryPolicy.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\nimport type { RetryPolicy } from \"./RetryPolicy.js\";\nimport { StatusCodes } from \"../common/statusCodes.js\";\nimport type { GlobalEndpointManager } from \"../globalEndpointManager.js\";\nimport { HTTPMethod, isReadRequest } from \"../common/index.js\";\nimport type { OperationType, ResourceType } from \"../common/constants.js\";\nimport { Constants } from \"../common/constants.js\";\nimport type { RetryContext } from \"./RetryContext.js\";\nimport type { CosmosHeaders } from \"../queryExecutionContext/CosmosHeaders.js\";\nimport { TimeoutErrorCode } from \"../request/TimeoutError.js\";\nimport type { ErrorResponse, RequestContext } from \"../request/index.js\";\nimport type { DiagnosticNodeInternal } from \"../diagnostics/DiagnosticNodeInternal.js\";\nimport { GlobalPartitionEndpointManager } from \"../globalPartitionEndpointManager.js\";\n\n/**\n * This class TimeoutFailoverRetryPolicy handles retries for read operations\n * (including data plane,metadata, and query plan) in case of request timeouts\n * (TimeoutError) or service unavailability (503 status code) by performing failover\n * and retrying on other regions.\n * @hidden\n */\nexport class TimeoutFailoverRetryPolicy implements RetryPolicy {\n private maxRetryAttemptCount = 120;\n private maxServiceUnavailableRetryCount = 1;\n public retryAfterInMs = 0;\n public failoverRetryCount = 0;\n public request: any;\n public locationEndpoint: any;\n\n constructor(\n private globalEndpointManager: GlobalEndpointManager,\n private headers: CosmosHeaders,\n private methodType: HTTPMethod,\n private resourceType: ResourceType,\n private operationType: OperationType,\n private enableEndPointDiscovery: boolean,\n private globalPartitionEndpointManager?: GlobalPartitionEndpointManager,\n ) {}\n\n /**\n * Checks if a timeout request is valid for the timeout failover retry policy.\n * A valid request should be a data plane, metadata, or query plan request.\n * @returns\n */\n private isValidRequestForTimeoutError(): boolean {\n const isQuery = Constants.HttpHeaders.IsQuery in this.headers;\n const isQueryPlan = Constants.HttpHeaders.IsQueryPlan in this.headers;\n if (this.methodType === HTTPMethod.get || isQuery || isQueryPlan) {\n return true;\n }\n return false;\n }\n\n public async shouldRetry(\n err: ErrorResponse,\n diagnosticNode: DiagnosticNodeInternal,\n retryContext?: RetryContext,\n locationEndpoint?: string,\n requestContext?: RequestContext,\n ): Promise<boolean> {\n if (!err) {\n return false;\n }\n if (!retryContext || !locationEndpoint) {\n return false;\n }\n if (!this.enableEndPointDiscovery) {\n return false;\n }\n // Mark the partition as unavailable.\n // Let the Retry logic decide if the request should be retried\n if (requestContext && this.globalPartitionEndpointManager) {\n await this.globalPartitionEndpointManager.tryPartitionLevelFailover(\n requestContext,\n diagnosticNode,\n );\n }\n // Check if the error is a timeout error (TimeoutErrorCode) and if it is not a valid HTTP network timeout request\n if (err.code === TimeoutErrorCode && !this.isValidRequestForTimeoutError()) {\n return false;\n }\n if (\n err.code === StatusCodes.ServiceUnavailable &&\n this.failoverRetryCount >= this.maxServiceUnavailableRetryCount\n ) {\n return false;\n }\n if (this.failoverRetryCount >= this.maxRetryAttemptCount) {\n return false;\n }\n const canUseMultipleWriteLocations = this.globalEndpointManager.canUseMultipleWriteLocations(\n this.resourceType,\n this.operationType,\n );\n const readRequest = isReadRequest(this.operationType);\n\n if (\n !canUseMultipleWriteLocations &&\n !readRequest &&\n !this.globalPartitionEndpointManager?.isPartitionLevelAutomaticFailoverEnabled()\n ) {\n // Write requests on single master cannot be retried if partition level failover is disabled.\n // This means there are no other regions available to serve the writes.\n return false;\n }\n this.failoverRetryCount++;\n // Setting the retryLocationIndex to the next available location for retry.\n // The retryLocationIndex is determined based on the failoverRetryCount, starting from zero.\n retryContext.retryLocationServerIndex = await this.findEndpointIndex(this.failoverRetryCount);\n diagnosticNode.addData({ successfulRetryPolicy: \"timeout-failover\" });\n return true;\n }\n\n /**\n * Determines index of endpoint to be used for retry based upon failoverRetryCount and avalable locations\n * @param failoverRetryCount - count of failovers\n * @returns\n */\n private async findEndpointIndex(failoverRetryCount: number): Promise<number> {\n // count of preferred locations specified by user\n const preferredLocationsCount = this.globalEndpointManager.preferredLocationsCount;\n const readRequest = isReadRequest(this.operationType);\n let endpointIndex = 0;\n // If preferredLocationsCount is not zero, it indicates that the user has specified preferred locations.\n if (preferredLocationsCount !== 0) {\n // The endpointIndex is set based on the preferred location and the failover retry count.\n endpointIndex = failoverRetryCount % preferredLocationsCount;\n } else {\n // In the absence of preferred locations, the endpoint selection is based on the failover count and the number of available locations.\n if (readRequest) {\n const getReadEndpoints = await this.globalEndpointManager.getReadEndpoints();\n if (getReadEndpoints && getReadEndpoints.length > 0) {\n endpointIndex = failoverRetryCount % getReadEndpoints.length;\n }\n } else {\n const getWriteEndpoints = await this.globalEndpointManager.getWriteEndpoints();\n if (getWriteEndpoints && getWriteEndpoints.length > 0) {\n endpointIndex = failoverRetryCount % getWriteEndpoints.length;\n }\n }\n }\n return endpointIndex;\n }\n}\n"]}
|
|
@@ -755,8 +755,8 @@ export class ClientContext {
|
|
|
755
755
|
* @internal
|
|
756
756
|
*/
|
|
757
757
|
isPartitionLevelFailOverEnabled() {
|
|
758
|
-
return (this.globalEndpointManager.
|
|
759
|
-
this.globalEndpointManager.
|
|
758
|
+
return (this.globalEndpointManager.lastKnownPPAFEnabled ||
|
|
759
|
+
this.globalEndpointManager.lastKnownPPCBEnabled);
|
|
760
760
|
}
|
|
761
761
|
}
|
|
762
762
|
//# sourceMappingURL=ClientContext.js.map
|