Added throughput bucketing

This commit is contained in:
Sung-Hyun Kang 2025-01-12 21:28:30 -06:00
parent 4b75e86b74
commit aa39359460
37 changed files with 466 additions and 129 deletions

8
package-lock.json generated
View File

@ -10,7 +10,7 @@
"hasInstallScript": true, "hasInstallScript": true,
"dependencies": { "dependencies": {
"@azure/arm-cosmosdb": "9.1.0", "@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "4.2.0-beta.1", "@azure/cosmos": "4.2.0",
"@azure/cosmos-language-service": "0.0.5", "@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.5.2", "@azure/identity": "1.5.2",
"@azure/ms-rest-nodeauth": "3.1.1", "@azure/ms-rest-nodeauth": "3.1.1",
@ -378,9 +378,9 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/@azure/cosmos": { "node_modules/@azure/cosmos": {
"version": "4.2.0-beta.1", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.2.0-beta.1.tgz", "resolved": "https://registry.npmjs.org/@azure/cosmos/-/cosmos-4.2.0.tgz",
"integrity": "sha512-mREONehm1DxjEKXGaNU6Wmpf9Ckb9IrhKFXhDFVs45pxmoEb3y2s/Ub0owuFmqlphpcS1zgtYQn5exn+lwnJuQ==", "integrity": "sha512-acfAQTYLxgB/iZK7XvTVYe9NPk6DECEgcIXDQhyn7Uo4dGxeeW5D3YqLjLJrrzND5Iawer3eUQ5/iiLWvTGAxQ==",
"dependencies": { "dependencies": {
"@azure/abort-controller": "^2.0.0", "@azure/abort-controller": "^2.0.0",
"@azure/core-auth": "^1.7.1", "@azure/core-auth": "^1.7.1",

View File

@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"dependencies": { "dependencies": {
"@azure/arm-cosmosdb": "9.1.0", "@azure/arm-cosmosdb": "9.1.0",
"@azure/cosmos": "4.2.0-beta.1", "@azure/cosmos": "4.2.0",
"@azure/cosmos-language-service": "0.0.5", "@azure/cosmos-language-service": "0.0.5",
"@azure/identity": "1.5.2", "@azure/identity": "1.5.2",
"@azure/ms-rest-nodeauth": "3.1.1", "@azure/ms-rest-nodeauth": "3.1.1",

View File

@ -1,4 +1,3 @@
import { QueryOperationOptions } from "@azure/cosmos";
import { QueryResults } from "../Contracts/ViewModels"; import { QueryResults } from "../Contracts/ViewModels";
interface QueryResponse { interface QueryResponse {
@ -11,17 +10,13 @@ interface QueryResponse {
} }
export interface MinimalQueryIterator { export interface MinimalQueryIterator {
fetchNext: (queryOperationOptions?: QueryOperationOptions) => Promise<QueryResponse>; fetchNext: () => Promise<QueryResponse>;
} }
// Pick<QueryIterator<any>, "fetchNext">; // Pick<QueryIterator<any>, "fetchNext">;
export function nextPage( export function nextPage(documentsIterator: MinimalQueryIterator, firstItemIndex: number): Promise<QueryResults> {
documentsIterator: MinimalQueryIterator, return documentsIterator.fetchNext().then((response) => {
firstItemIndex: number,
queryOperationOptions?: QueryOperationOptions,
): Promise<QueryResults> {
return documentsIterator.fetchNext(queryOperationOptions).then((response) => {
const documents = response.resources; const documents = response.resources;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const headers = (response as any).headers || {}; // TODO this is a private key. Remove any const headers = (response as any).headers || {}; // TODO this is a private key. Remove any

View File

@ -28,5 +28,9 @@ export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => {
Queries.itemsPerPage; Queries.itemsPerPage;
options.maxDegreeOfParallelism = LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism); options.maxDegreeOfParallelism = LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism);
options.disableNonStreamingOrderByQuery = !isVectorSearchEnabled(); options.disableNonStreamingOrderByQuery = !isVectorSearchEnabled();
options.initialHeaders = {
...options.initialHeaders,
"x-ms-cosmos-throughput-bucket": "1",
};
return options; return options;
}; };

View File

@ -1,4 +1,3 @@
import { QueryOperationOptions } from "@azure/cosmos";
import { QueryResults } from "../../Contracts/ViewModels"; import { QueryResults } from "../../Contracts/ViewModels";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { getEntityName } from "../DocumentUtility"; import { getEntityName } from "../DocumentUtility";
@ -9,13 +8,12 @@ export const queryDocumentsPage = async (
resourceName: string, resourceName: string,
documentsIterator: MinimalQueryIterator, documentsIterator: MinimalQueryIterator,
firstItemIndex: number, firstItemIndex: number,
queryOperationOptions?: QueryOperationOptions,
): Promise<QueryResults> => { ): Promise<QueryResults> => {
const entityName = getEntityName(); const entityName = getEntityName();
const clearMessage = logConsoleProgress(`Querying ${entityName} for container ${resourceName}`); const clearMessage = logConsoleProgress(`Querying ${entityName} for container ${resourceName}`);
try { try {
const result: QueryResults = await nextPage(documentsIterator, firstItemIndex, queryOperationOptions); const result: QueryResults = await nextPage(documentsIterator, firstItemIndex);
const itemCount = (result.documents && result.documents.length) || 0; const itemCount = (result.documents && result.documents.length) || 0;
logConsoleInfo(`Successfully fetched ${itemCount} ${entityName} for container ${resourceName}`); logConsoleInfo(`Successfully fetched ${itemCount} ${entityName} for container ${resourceName}`);
return result; return result;

View File

@ -105,6 +105,8 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
? parseInt(resource.softAllowedMaximumThroughput) ? parseInt(resource.softAllowedMaximumThroughput)
: resource.softAllowedMaximumThroughput; : resource.softAllowedMaximumThroughput;
const throughputBuckets = resource?.throughputBuckets;
if (autoscaleSettings) { if (autoscaleSettings) {
return { return {
id: offerId, id: offerId,
@ -114,6 +116,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
offerReplacePending: resource.offerReplacePending === "true", offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput, instantMaximumThroughput,
softAllowedMaximumThroughput, softAllowedMaximumThroughput,
throughputBuckets,
}; };
} }
@ -125,6 +128,7 @@ const readCollectionOfferWithARM = async (databaseId: string, collectionId: stri
offerReplacePending: resource.offerReplacePending === "true", offerReplacePending: resource.offerReplacePending === "true",
instantMaximumThroughput, instantMaximumThroughput,
softAllowedMaximumThroughput, softAllowedMaximumThroughput,
throughputBuckets,
}; };
} }

View File

@ -1,6 +1,6 @@
import { OfferDefinition, RequestOptions } from "@azure/cosmos"; import { OfferDefinition, RequestOptions } from "@azure/cosmos";
import { AuthType } from "../../AuthType"; import { AuthType } from "../../AuthType";
import { Offer, SDKOfferDefinition, UpdateOfferParams } from "../../Contracts/DataModels"; import { Offer, SDKOfferDefinition, ThroughputBucket, UpdateOfferParams } from "../../Contracts/DataModels";
import { userContext } from "../../UserContext"; import { userContext } from "../../UserContext";
import { import {
migrateCassandraKeyspaceToAutoscale, migrateCassandraKeyspaceToAutoscale,
@ -359,6 +359,13 @@ const createUpdateOfferBody = (params: UpdateOfferParams): ThroughputSettingsUpd
body.properties.resource.throughput = params.manualThroughput; body.properties.resource.throughput = params.manualThroughput;
} }
if (params.throughputBuckets) {
const throughputBuckets = params.throughputBuckets.filter(
(bucket: ThroughputBucket) => bucket.maxThroughputPercentage !== 100,
);
body.properties.resource.throughputBuckets = throughputBuckets;
}
return body; return body;
}; };

View File

@ -274,6 +274,12 @@ export interface Offer {
offerReplacePending: boolean; offerReplacePending: boolean;
instantMaximumThroughput?: number; instantMaximumThroughput?: number;
softAllowedMaximumThroughput?: number; softAllowedMaximumThroughput?: number;
throughputBuckets?: ThroughputBucket[];
}
export interface ThroughputBucket {
id: number;
maxThroughputPercentage: number;
} }
export interface SDKOfferDefinition extends Resource { export interface SDKOfferDefinition extends Resource {
@ -396,6 +402,7 @@ export interface UpdateOfferParams {
collectionId?: string; collectionId?: string;
migrateToAutoPilot?: boolean; migrateToAutoPilot?: boolean;
migrateToManual?: boolean; migrateToManual?: boolean;
throughputBuckets?: ThroughputBucket[];
} }
export interface Notification { export interface Notification {

View File

@ -86,6 +86,8 @@ export interface SettingsComponentState {
wasAutopilotOriginallySet: boolean; wasAutopilotOriginallySet: boolean;
isScaleSaveable: boolean; isScaleSaveable: boolean;
isScaleDiscardable: boolean; isScaleDiscardable: boolean;
throughputBuckets: DataModels.ThroughputBucket[];
throughputBucketsBaseline: DataModels.ThroughputBucket[];
throughputError: string; throughputError: string;
timeToLive: TtlType; timeToLive: TtlType;
@ -158,6 +160,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
private isVectorSearchEnabled: boolean; private isVectorSearchEnabled: boolean;
private isFullTextSearchEnabled: boolean; private isFullTextSearchEnabled: boolean;
private totalThroughputUsed: number; private totalThroughputUsed: number;
private throughputBucketsEnabled: boolean;
public mongoDBCollectionResource: MongoDBCollectionResource; public mongoDBCollectionResource: MongoDBCollectionResource;
constructor(props: SettingsComponentProps) { constructor(props: SettingsComponentProps) {
@ -175,6 +178,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
this.isFullTextSearchEnabled = isFullTextSearchEnabled() && !hasDatabaseSharedThroughput(this.collection); this.isFullTextSearchEnabled = isFullTextSearchEnabled() && !hasDatabaseSharedThroughput(this.collection);
this.changeFeedPolicyVisible = userContext.features.enableChangeFeedPolicy; this.changeFeedPolicyVisible = userContext.features.enableChangeFeedPolicy;
this.throughputBucketsEnabled =
userContext.features.enableThroughputBuckets && userContext.authType === AuthType.AAD;
// Mongo container with system partition key still treat as "Fixed" // Mongo container with system partition key still treat as "Fixed"
this.isFixedContainer = this.isFixedContainer =
@ -193,6 +198,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
wasAutopilotOriginallySet: false, wasAutopilotOriginallySet: false,
isScaleSaveable: false, isScaleSaveable: false,
isScaleDiscardable: false, isScaleDiscardable: false,
throughputBuckets: undefined,
throughputBucketsBaseline: undefined,
throughputError: undefined, throughputError: undefined,
timeToLive: undefined, timeToLive: undefined,
@ -419,6 +426,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
this.setState({ this.setState({
throughput: this.state.throughputBaseline, throughput: this.state.throughputBaseline,
throughputBuckets: this.state.throughputBucketsBaseline,
throughputBucketsBaseline: this.state.throughputBucketsBaseline,
timeToLive: this.state.timeToLiveBaseline, timeToLive: this.state.timeToLiveBaseline,
timeToLiveSeconds: this.state.timeToLiveSecondsBaseline, timeToLiveSeconds: this.state.timeToLiveSecondsBaseline,
displayedTtlSeconds: this.state.displayedTtlSecondsBaseline, displayedTtlSeconds: this.state.displayedTtlSecondsBaseline,
@ -749,9 +758,13 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
] as DataModels.ComputedProperties; ] as DataModels.ComputedProperties;
} }
const throughputBuckets = this.offer?.throughputBuckets;
return { return {
throughput: offerThroughput, throughput: offerThroughput,
throughputBaseline: offerThroughput, throughputBaseline: offerThroughput,
throughputBuckets,
throughputBucketsBaseline: throughputBuckets,
changeFeedPolicy: changeFeedPolicy, changeFeedPolicy: changeFeedPolicy,
changeFeedPolicyBaseline: changeFeedPolicy, changeFeedPolicyBaseline: changeFeedPolicy,
timeToLive: timeToLive, timeToLive: timeToLive,
@ -839,6 +852,10 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
this.setState({ throughput: newThroughput, throughputError }); this.setState({ throughput: newThroughput, throughputError });
}; };
private onThroughputBucketChange = (throughputBuckets: DataModels.ThroughputBucket[]): void => {
this.setState({ throughputBuckets });
};
private onAutoPilotSelected = (isAutoPilotSelected: boolean): void => private onAutoPilotSelected = (isAutoPilotSelected: boolean): void =>
this.setState({ isAutoPilotSelected: isAutoPilotSelected }); this.setState({ isAutoPilotSelected: isAutoPilotSelected });
@ -1036,6 +1053,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
currentOffer: this.collection.offer(), currentOffer: this.collection.offer(),
autopilotThroughput: this.state.isAutoPilotSelected ? this.state.autoPilotThroughput : undefined, autopilotThroughput: this.state.isAutoPilotSelected ? this.state.autoPilotThroughput : undefined,
manualThroughput: this.state.isAutoPilotSelected ? undefined : this.state.throughput, manualThroughput: this.state.isAutoPilotSelected ? undefined : this.state.throughput,
...(this.state.throughputBuckets && { throughputBuckets: this.state.throughputBuckets }),
}; };
if (this.hasProvisioningTypeChanged()) { if (this.hasProvisioningTypeChanged()) {
if (this.state.isAutoPilotSelected) { if (this.state.isAutoPilotSelected) {
@ -1102,6 +1120,10 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
onMaxAutoPilotThroughputChange: this.onMaxAutoPilotThroughputChange, onMaxAutoPilotThroughputChange: this.onMaxAutoPilotThroughputChange,
onScaleSaveableChange: this.onScaleSaveableChange, onScaleSaveableChange: this.onScaleSaveableChange,
onScaleDiscardableChange: this.onScaleDiscardableChange, onScaleDiscardableChange: this.onScaleDiscardableChange,
throughputBucketsBaseline: this.state.throughputBucketsBaseline,
throughputBuckets: this.state.throughputBuckets,
enableThroughputBuckets: this.isCollectionSettingsTab && this.throughputBucketsEnabled,
onThroughputBucketChange: this.onThroughputBucketChange,
throughputError: this.state.throughputError, throughputError: this.state.throughputError,
}; };

View File

@ -16,6 +16,7 @@ import {
titleAndInputStackProps, titleAndInputStackProps,
} from "../SettingsRenderUtils"; } from "../SettingsRenderUtils";
import { hasDatabaseSharedThroughput } from "../SettingsUtils"; import { hasDatabaseSharedThroughput } from "../SettingsUtils";
import { ThroughputBucketsComponent } from "./ThroughputInputComponents/ThroughputBucketsComponent";
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component"; import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
export interface ScaleComponentProps { export interface ScaleComponentProps {
@ -33,10 +34,21 @@ export interface ScaleComponentProps {
onMaxAutoPilotThroughputChange: (newThroughput: number) => void; onMaxAutoPilotThroughputChange: (newThroughput: number) => void;
onScaleSaveableChange: (isScaleSaveable: boolean) => void; onScaleSaveableChange: (isScaleSaveable: boolean) => void;
onScaleDiscardableChange: (isScaleDiscardable: boolean) => void; onScaleDiscardableChange: (isScaleDiscardable: boolean) => void;
throughputBuckets: DataModels.ThroughputBucket[];
throughputBucketsBaseline: DataModels.ThroughputBucket[];
enableThroughputBuckets: boolean;
onThroughputBucketChange: (throughputBuckets: DataModels.ThroughputBucket[]) => void;
throughputError?: string; throughputError?: string;
} }
export class ScaleComponent extends React.Component<ScaleComponentProps> { interface ScaleComponentState {
isThroughputSaveable: boolean;
isBucketsSaveable: boolean;
isThroughputDiscardable: boolean;
isBucketsDiscardable: boolean;
}
export class ScaleComponent extends React.Component<ScaleComponentProps, ScaleComponentState> {
private isEmulator: boolean; private isEmulator: boolean;
private offer: DataModels.Offer; private offer: DataModels.Offer;
private databaseId: string; private databaseId: string;
@ -48,6 +60,13 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
this.offer = this.props.database?.offer() || this.props.collection?.offer(); this.offer = this.props.database?.offer() || this.props.collection?.offer();
this.databaseId = this.props.database?.id() || this.props.collection.databaseId; this.databaseId = this.props.database?.id() || this.props.collection.databaseId;
this.collectionId = this.props.collection?.id(); this.collectionId = this.props.collection?.id();
this.state = {
isThroughputSaveable: false,
isBucketsSaveable: false,
isThroughputDiscardable: false,
isBucketsDiscardable: false,
};
console.log(this.offer);
} }
public isAutoScaleEnabled = (): boolean => { public isAutoScaleEnabled = (): boolean => {
@ -137,8 +156,8 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
maxAutoPilotThroughputBaseline={this.props.autoPilotThroughputBaseline} maxAutoPilotThroughputBaseline={this.props.autoPilotThroughputBaseline}
onMaxAutoPilotThroughputChange={this.props.onMaxAutoPilotThroughputChange} onMaxAutoPilotThroughputChange={this.props.onMaxAutoPilotThroughputChange}
spendAckChecked={false} spendAckChecked={false}
onScaleSaveableChange={this.props.onScaleSaveableChange} onScaleSaveableChange={this.handleThroughputSaveableChange}
onScaleDiscardableChange={this.props.onScaleDiscardableChange} onScaleDiscardableChange={this.handleThroughputDiscardableChange}
usageSizeInKB={this.props.collection?.usageSizeInKB()} usageSizeInKB={this.props.collection?.usageSizeInKB()}
throughputError={this.props.throughputError} throughputError={this.props.throughputError}
instantMaximumThroughput={this.offer?.instantMaximumThroughput} instantMaximumThroughput={this.offer?.instantMaximumThroughput}
@ -167,6 +186,39 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
); );
} }
private updateScaleSettingsState = (updates: Partial<ScaleComponentState>) => {
this.setState(
(prevState) => {
const hasChanges = Object.keys(updates).some(
(key) => prevState[key as keyof ScaleComponentState] !== updates[key as keyof ScaleComponentState],
);
return hasChanges ? { ...prevState, ...updates } : null;
},
() => {
const isSaveable = this.state.isThroughputSaveable || this.state.isBucketsSaveable;
const isDiscardable = this.state.isThroughputDiscardable || this.state.isBucketsDiscardable;
this.props.onScaleSaveableChange(isSaveable);
this.props.onScaleDiscardableChange(isDiscardable);
},
);
};
private handleThroughputSaveableChange = (isSaveable: boolean) => {
this.updateScaleSettingsState({ isThroughputSaveable: isSaveable });
};
private handleThroughputDiscardableChange = (isDiscardable: boolean) => {
this.updateScaleSettingsState({ isThroughputDiscardable: isDiscardable });
};
private handleBucketsSaveableChange = (isSaveable: boolean) => {
this.updateScaleSettingsState({ isBucketsSaveable: isSaveable });
};
private handleBucketsDiscardableChange = (isDiscardable: boolean) => {
this.updateScaleSettingsState({ isBucketsDiscardable: isDiscardable });
};
public render(): JSX.Element { public render(): JSX.Element {
return ( return (
<Stack {...subComponentStackProps}> <Stack {...subComponentStackProps}>
@ -182,6 +234,15 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
<MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar> <MessageBar messageBarType={MessageBarType.warning}>{this.getInitialNotificationElement()}</MessageBar>
)} )}
{!this.isAutoScaleEnabled() && <Stack {...subComponentStackProps}>{this.getThroughputInputComponent()}</Stack>} {!this.isAutoScaleEnabled() && <Stack {...subComponentStackProps}>{this.getThroughputInputComponent()}</Stack>}
{this.props.enableThroughputBuckets && (
<ThroughputBucketsComponent
currentBuckets={this.props.throughputBuckets}
throughputBucketsBaseline={this.props.throughputBucketsBaseline}
onBucketsChange={this.props.onThroughputBucketChange}
onSaveableChange={this.handleBucketsSaveableChange}
onDiscardableChange={this.handleBucketsDiscardableChange}
/>
)}
{/* TODO: Replace link with call to the Azure Support blade */} {/* TODO: Replace link with call to the Azure Support blade */}
{this.isAutoScaleEnabled() && ( {this.isAutoScaleEnabled() && (

View File

@ -0,0 +1,129 @@
import "@testing-library/jest-dom";
import { fireEvent, render, screen } from "@testing-library/react";
import React from "react";
import { ThroughputBucketsComponent } from "./ThroughputBucketsComponent";
describe("ThroughputBucketsComponent", () => {
const mockOnBucketsChange = jest.fn();
const mockOnSaveableChange = jest.fn();
const mockOnDiscardableChange = jest.fn();
const defaultProps = {
currentBuckets: [
{ id: 1, maxThroughputPercentage: 50 },
{ id: 2, maxThroughputPercentage: 60 },
],
throughputBucketsBaseline: [
{ id: 1, maxThroughputPercentage: 40 },
{ id: 2, maxThroughputPercentage: 50 },
],
onBucketsChange: mockOnBucketsChange,
onSaveableChange: mockOnSaveableChange,
onDiscardableChange: mockOnDiscardableChange,
};
beforeEach(() => {
jest.clearAllMocks();
});
it("renders 5 buckets with default values when input buckets are missing", () => {
render(<ThroughputBucketsComponent {...defaultProps} currentBuckets={[{ id: 1, maxThroughputPercentage: 50 }]} />);
expect(screen.getAllByText(/Bucket \d+/)).toHaveLength(5);
expect(screen.getByDisplayValue("50")).toBeInTheDocument();
expect(screen.getAllByDisplayValue("100").length).toBe(4);
});
it("renders buckets in the correct order even if input is unordered", () => {
const unorderedBuckets = [
{ id: 2, maxThroughputPercentage: 60 },
{ id: 1, maxThroughputPercentage: 50 },
];
render(<ThroughputBucketsComponent {...defaultProps} currentBuckets={unorderedBuckets} />);
const bucketLabels = screen.getAllByText(/Bucket \d+/).map((el) => el.textContent);
expect(bucketLabels).toEqual(["Bucket 1", "Bucket 2", "Bucket 3", "Bucket 4", "Bucket 5"]);
expect(screen.getByDisplayValue("50")).toBeInTheDocument();
expect(screen.getByDisplayValue("60")).toBeInTheDocument();
expect(screen.getAllByDisplayValue("100").length).toBe(3);
});
it("calls onBucketsChange when a bucket value changes", () => {
render(<ThroughputBucketsComponent {...defaultProps} />);
const input = screen.getByDisplayValue("50");
fireEvent.change(input, { target: { value: "70" } });
expect(mockOnBucketsChange).toHaveBeenCalledWith([
{ id: 1, maxThroughputPercentage: 70 },
{ id: 2, maxThroughputPercentage: 60 },
{ id: 3, maxThroughputPercentage: 100 },
{ id: 4, maxThroughputPercentage: 100 },
{ id: 5, maxThroughputPercentage: 100 },
]);
});
it("triggers onSaveableChange and onDiscardableChange when values change", () => {
render(<ThroughputBucketsComponent {...defaultProps} />);
const input = screen.getByDisplayValue("50");
fireEvent.change(input, { target: { value: "80" } });
expect(mockOnSaveableChange).toHaveBeenCalledWith(true);
expect(mockOnDiscardableChange).toHaveBeenCalledWith(true);
});
it("ensures buckets revert to default when no buckets are provided", () => {
render(<ThroughputBucketsComponent {...defaultProps} currentBuckets={[]} />);
expect(screen.getAllByText(/Bucket \d+/)).toHaveLength(5);
expect(screen.getAllByDisplayValue("100")).toHaveLength(5);
});
it("updates state consistently after multiple changes to different buckets", () => {
render(<ThroughputBucketsComponent {...defaultProps} />);
const input1 = screen.getByDisplayValue("50");
fireEvent.change(input1, { target: { value: "70" } });
const input2 = screen.getByDisplayValue("60");
fireEvent.change(input2, { target: { value: "80" } });
expect(mockOnBucketsChange).toHaveBeenCalledWith([
{ id: 1, maxThroughputPercentage: 70 },
{ id: 2, maxThroughputPercentage: 80 },
{ id: 3, maxThroughputPercentage: 100 },
{ id: 4, maxThroughputPercentage: 100 },
{ id: 5, maxThroughputPercentage: 100 },
]);
});
it("resets to baseline when currentBuckets are reset", () => {
const { rerender } = render(<ThroughputBucketsComponent {...defaultProps} />);
const input1 = screen.getByDisplayValue("50");
fireEvent.change(input1, { target: { value: "70" } });
expect(mockOnBucketsChange).toHaveBeenCalledWith([
{ id: 1, maxThroughputPercentage: 70 },
{ id: 2, maxThroughputPercentage: 60 },
{ id: 3, maxThroughputPercentage: 100 },
{ id: 4, maxThroughputPercentage: 100 },
{ id: 5, maxThroughputPercentage: 100 },
]);
rerender(<ThroughputBucketsComponent {...defaultProps} currentBuckets={defaultProps.throughputBucketsBaseline} />);
expect(screen.getByDisplayValue("40")).toBeInTheDocument();
expect(screen.getByDisplayValue("50")).toBeInTheDocument();
});
it("does not call onBucketsChange when value remains unchanged", () => {
render(<ThroughputBucketsComponent {...defaultProps} />);
const input = screen.getByDisplayValue("50");
fireEvent.change(input, { target: { value: "50" } });
expect(mockOnBucketsChange).not.toHaveBeenCalled();
});
});

View File

@ -0,0 +1,92 @@
import { Icon, Label, Slider, Stack, TextField } from "@fluentui/react";
import { ThroughputBucket } from "Contracts/DataModels";
import React, { FC, useEffect, useState } from "react";
import { isDirty } from "../../SettingsUtils";
const MAX_BUCKET_SIZES = 5;
const DEFAULT_BUCKETS = Array.from({ length: MAX_BUCKET_SIZES }, (_, i) => ({
id: i + 1,
maxThroughputPercentage: 100,
}));
interface ThroughputBucketsComponentProps {
currentBuckets: ThroughputBucket[];
throughputBucketsBaseline: ThroughputBucket[];
onBucketsChange: (updatedBuckets: ThroughputBucket[]) => void;
onSaveableChange: (isSaveable: boolean) => void;
onDiscardableChange: (isDiscardable: boolean) => void;
}
export const ThroughputBucketsComponent: FC<ThroughputBucketsComponentProps> = ({
currentBuckets,
throughputBucketsBaseline,
onBucketsChange,
onSaveableChange,
onDiscardableChange,
}) => {
const getThroughputBuckets = (buckets: ThroughputBucket[]): ThroughputBucket[] => {
return DEFAULT_BUCKETS.map(
(defaultBucket) => buckets.find((bucket) => bucket.id === defaultBucket.id) || defaultBucket,
);
};
const [throughputBuckets, setThroughputBuckets] = useState<ThroughputBucket[]>(getThroughputBuckets(currentBuckets));
useEffect(() => {
const isChanged = isDirty(currentBuckets, getThroughputBuckets(throughputBucketsBaseline));
isChanged && setThroughputBuckets(getThroughputBuckets(currentBuckets));
}, [currentBuckets]);
useEffect(() => {
const isChanged = isDirty(throughputBuckets, getThroughputBuckets(throughputBucketsBaseline));
onSaveableChange(isChanged);
onDiscardableChange(isChanged);
}, [throughputBuckets]);
const handleBucketChange = (id: number, newValue: number) => {
const updatedBuckets = throughputBuckets.map((bucket) =>
bucket.id === id ? { ...bucket, maxThroughputPercentage: newValue } : bucket,
);
setThroughputBuckets(updatedBuckets);
const settingsChanged = isDirty(updatedBuckets, throughputBuckets);
settingsChanged && onBucketsChange(updatedBuckets);
};
return (
<Stack tokens={{ childrenGap: "m" }} styles={{ root: { width: "70%", maxWidth: 700 } }}>
<Label>Throughput buckets</Label>
<Stack>
{throughputBuckets?.map((bucket) => (
<Stack key={bucket.id} horizontal tokens={{ childrenGap: 8 }} verticalAlign="center">
<Slider
min={1}
max={100}
step={1}
value={bucket.maxThroughputPercentage}
onChange={(newValue) => handleBucketChange(bucket.id, newValue)}
showValue={false}
label={`Bucket ${bucket.id}`}
styles={{ root: { flex: 2, maxWidth: 400 } }}
/>
<TextField
value={bucket.maxThroughputPercentage.toString()}
onChange={(event, newValue) => handleBucketChange(bucket.id, parseInt(newValue || "0", 10))}
type="number"
suffix="%"
styles={{
fieldGroup: { width: 80 },
}}
/>
{bucket.id === 1 && (
<Stack horizontal tokens={{ childrenGap: 4 }} verticalAlign="center">
<Icon iconName="TagSolid" />
<span>Data Explorer Query Bucket</span>
</Stack>
)}
</Stack>
))}
</Stack>
</Stack>
);
};

View File

@ -11,7 +11,8 @@ export type isDirtyTypes =
| DataModels.IndexingPolicy | DataModels.IndexingPolicy
| DataModels.ComputedProperties | DataModels.ComputedProperties
| DataModels.VectorEmbedding[] | DataModels.VectorEmbedding[]
| DataModels.FullTextPolicy; | DataModels.FullTextPolicy
| DataModels.ThroughputBucket[];
export const TtlOff = "off"; export const TtlOff = "off";
export const TtlOn = "on"; export const TtlOn = "on";
export const TtlOnNoDefault = "on-nodefault"; export const TtlOnNoDefault = "on-nodefault";

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable no-console */ /* eslint-disable no-console */
import { FeedOptions, QueryOperationOptions } from "@azure/cosmos"; import { FeedOptions } from "@azure/cosmos";
import QueryError, { createMonacoErrorLocationResolver, createMonacoMarkersForQueryErrors } from "Common/QueryError"; import QueryError, { createMonacoErrorLocationResolver, createMonacoMarkersForQueryErrors } from "Common/QueryError";
import { SplitterDirection } from "Common/Splitter"; import { SplitterDirection } from "Common/Splitter";
import { Platform, configContext } from "ConfigContext"; import { Platform, configContext } from "ConfigContext";
@ -18,7 +18,7 @@ import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
import { useSelectedNode } from "Explorer/useSelectedNode"; import { useSelectedNode } from "Explorer/useSelectedNode";
import { KeyboardAction } from "KeyboardShortcuts"; import { KeyboardAction } from "KeyboardShortcuts";
import { QueryConstants } from "Shared/Constants"; import { QueryConstants } from "Shared/Constants";
import { LocalStorageUtility, StorageKey, getRUThreshold, ruThresholdEnabled } from "Shared/StorageUtility"; import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
import { Action } from "Shared/Telemetry/TelemetryConstants"; import { Action } from "Shared/Telemetry/TelemetryConstants";
import { Allotment } from "allotment"; import { Allotment } from "allotment";
import { QueryCopilotState, useQueryCopilot } from "hooks/useQueryCopilot"; import { QueryCopilotState, useQueryCopilot } from "hooks/useQueryCopilot";
@ -368,20 +368,8 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
isExecutionError: false, isExecutionError: false,
}); });
let queryOperationOptions: QueryOperationOptions;
if (userContext.apiType === "SQL" && ruThresholdEnabled()) {
const ruThreshold: number = getRUThreshold();
queryOperationOptions = {
ruCapPerOperation: ruThreshold,
} as QueryOperationOptions;
}
const queryDocuments = async (firstItemIndex: number) => const queryDocuments = async (firstItemIndex: number) =>
await queryDocumentsPage( await queryDocumentsPage(this.props.collection && this.props.collection.id(), this._iterator, firstItemIndex);
this.props.collection && this.props.collection.id(),
this._iterator,
firstItemIndex,
queryOperationOptions,
);
this.props.tabsBaseInstance.isExecuting(true); this.props.tabsBaseInstance.isExecuting(true);
this.setState({ this.setState({
isExecuting: true, isExecuting: true,

View File

@ -16,6 +16,7 @@ export type Features = {
readonly enableAadDataPlane: boolean; readonly enableAadDataPlane: boolean;
readonly enableResourceGraph: boolean; readonly enableResourceGraph: boolean;
readonly enableKoResourceTree: boolean; readonly enableKoResourceTree: boolean;
readonly enableThroughputBuckets: boolean;
readonly hostedDataExplorer: boolean; readonly hostedDataExplorer: boolean;
readonly junoEndpoint?: string; readonly junoEndpoint?: string;
readonly phoenixEndpoint?: string; readonly phoenixEndpoint?: string;
@ -82,6 +83,7 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
enableSpark: "true" === get("enablespark"), enableSpark: "true" === get("enablespark"),
enableTtl: "true" === get("enablettl"), enableTtl: "true" === get("enablettl"),
enableKoResourceTree: "true" === get("enablekoresourcetree"), enableKoResourceTree: "true" === get("enablekoresourcetree"),
enableThroughputBuckets: "true" === get("enablethroughputbuckets"),
executeSproc: "true" === get("dataexplorerexecutesproc"), executeSproc: "true" === get("dataexplorerexecutesproc"),
hostedDataExplorer: "true" === get("hosteddataexplorerenabled"), hostedDataExplorer: "true" === get("hosteddataexplorerenabled"),
mongoProxyEndpoint: get("mongoproxyendpoint"), mongoProxyEndpoint: get("mongoproxyendpoint"),

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the Cassandra keyspaces under an existing Azure Cosmos DB database account. */ /* Lists the Cassandra keyspaces under an existing Azure Cosmos DB database account. */
export async function listCassandraKeyspaces( export async function listCassandraKeyspaces(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given database account and collection. */ /* Retrieves the metrics determined by the given filter for the given database account and collection. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given collection, split by partition. */ /* Retrieves the metrics determined by the given filter for the given collection, split by partition. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given collection and region, split by partition. */ /* Retrieves the metrics determined by the given filter for the given collection and region, split by partition. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given database account, collection and region. */ /* Retrieves the metrics determined by the given filter for the given database account, collection and region. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given database account and database. */ /* Retrieves the metrics determined by the given filter for the given database account and database. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given database account and region. */ /* Retrieves the metrics determined by the given filter for the given database account and region. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the properties of an existing Azure Cosmos DB database account. */ /* Retrieves the properties of an existing Azure Cosmos DB database account. */
export async function get( export async function get(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the graphs under an existing Azure Cosmos DB database account. */ /* Lists the graphs under an existing Azure Cosmos DB database account. */
export async function listGraphs( export async function listGraphs(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */ /* Lists the Gremlin databases under an existing Azure Cosmos DB database account. */
export async function listGremlinDatabases( export async function listGremlinDatabases(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* List Cosmos DB locations and their properties */ /* List Cosmos DB locations and their properties */
export async function list(subscriptionId: string): Promise<Types.LocationListResult | Types.CloudError> { export async function list(subscriptionId: string): Promise<Types.LocationListResult | Types.CloudError> {

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */ /* Lists the MongoDB databases under an existing Azure Cosmos DB database account. */
export async function listMongoDBDatabases( export async function listMongoDBDatabases(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists all of the available Cosmos DB Resource Provider operations. */ /* Lists all of the available Cosmos DB Resource Provider operations. */
export async function list(): Promise<Types.OperationListResult> { export async function list(): Promise<Types.OperationListResult> {

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given partition key range id. */ /* Retrieves the metrics determined by the given filter for the given partition key range id. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given partition key range id and region. */ /* Retrieves the metrics determined by the given filter for the given partition key range id and region. */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given database account. This url is only for PBS and Replication Latency data */ /* Retrieves the metrics determined by the given filter for the given database account. This url is only for PBS and Replication Latency data */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given account, source and target region. This url is only for PBS and Replication Latency data */ /* Retrieves the metrics determined by the given filter for the given account, source and target region. This url is only for PBS and Replication Latency data */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Retrieves the metrics determined by the given filter for the given account target region. This url is only for PBS and Replication Latency data */ /* Retrieves the metrics determined by the given filter for the given account target region. This url is only for PBS and Replication Latency data */
export async function listMetrics( export async function listMetrics(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-05-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the SQL databases under an existing Azure Cosmos DB database account. */ /* Lists the SQL databases under an existing Azure Cosmos DB database account. */
export async function listSqlDatabases( export async function listSqlDatabases(

View File

@ -3,13 +3,13 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
import { configContext } from "../../../../ConfigContext"; import { configContext } from "../../../../ConfigContext";
import { armRequest } from "../../request"; import { armRequest } from "../../request";
import * as Types from "./types"; import * as Types from "./types";
const apiVersion = "2024-02-15-preview"; const apiVersion = "2024-12-01-preview";
/* Lists the Tables under an existing Azure Cosmos DB database account. */ /* Lists the Tables under an existing Azure Cosmos DB database account. */
export async function listTables( export async function listTables(

View File

@ -3,7 +3,7 @@
Run "npm run generateARMClients" to regenerate Run "npm run generateARMClients" to regenerate
Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs Edting this file directly should be done with extreme caution as not to diverge from ARM REST specs
Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-02-15-preview/cosmos-db.json Generated from: https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/2024-12-01-preview/cosmos-db.json
*/ */
/* The List operation response, that contains the client encryption keys and their properties. */ /* The List operation response, that contains the client encryption keys and their properties. */
@ -553,6 +553,12 @@ export interface DatabaseAccountGetProperties {
/* The object that represents all properties related to capacity enforcement on an account. */ /* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity; capacity?: Capacity;
/* Indicates the capacityMode of the Cosmos DB account. */
capacityMode?: CapacityMode;
/* The object that represents the migration state for the CapacityMode of the Cosmos DB account. */
capacityModeChangeTransitionState?: CapacityModeChangeTransitionState;
/* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */ /* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */
enableMaterializedViews?: boolean; enableMaterializedViews?: boolean;
/* The object that represents the metadata for the Account Keys of the Cosmos DB account. */ /* The object that represents the metadata for the Account Keys of the Cosmos DB account. */
@ -652,6 +658,9 @@ export interface DatabaseAccountCreateUpdateProperties {
/* The object that represents all properties related to capacity enforcement on an account. */ /* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity; capacity?: Capacity;
/* Indicates the capacityMode of the Cosmos DB account. */
capacityMode?: CapacityMode;
/* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */ /* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */
enableMaterializedViews?: boolean; enableMaterializedViews?: boolean;
/* This property is ignored during the update/create operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */ /* This property is ignored during the update/create operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */
@ -754,6 +763,9 @@ export interface DatabaseAccountUpdateProperties {
/* The object that represents all properties related to capacity enforcement on an account. */ /* The object that represents all properties related to capacity enforcement on an account. */
capacity?: Capacity; capacity?: Capacity;
/* Indicates the capacityMode of the Cosmos DB account. */
capacityMode?: CapacityMode;
/* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */ /* Flag to indicate whether to enable MaterializedViews on the Cosmos DB account */
enableMaterializedViews?: boolean; enableMaterializedViews?: boolean;
/* This property is ignored during the update operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */ /* This property is ignored during the update operation, as the metadata is read-only. The object represents the metadata for the Account Keys of the Cosmos DB account. */
@ -1087,6 +1099,8 @@ export interface ThroughputSettingsResource {
readonly instantMaximumThroughput?: string; readonly instantMaximumThroughput?: string;
/* The maximum throughput value or the maximum maxThroughput value (for autoscale) that can be specified */ /* The maximum throughput value or the maximum maxThroughput value (for autoscale) that can be specified */
readonly softAllowedMaximumThroughput?: string; readonly softAllowedMaximumThroughput?: string;
/* Array of Throughput Bucket limits to be applied to the Cosmos DB container */
throughputBuckets?: ThroughputBucketResource[];
} }
/* Cosmos DB provisioned throughput settings object */ /* Cosmos DB provisioned throughput settings object */
@ -1114,6 +1128,14 @@ export interface ThroughputPolicyResource {
incrementPercent?: number; incrementPercent?: number;
} }
/* Cosmos DB throughput bucket object */
export interface ThroughputBucketResource {
/* Represents the throughput bucket id */
id: number;
/* Represents maximum percentage throughput that can be used by the bucket */
maxThroughputPercentage: number;
}
/* Cosmos DB options resource object */ /* Cosmos DB options resource object */
export interface OptionsResource { export interface OptionsResource {
/* Value of the Cosmos DB resource throughput or autoscaleSettings. Use the ThroughputSetting resource when retrieving offer details. */ /* Value of the Cosmos DB resource throughput or autoscaleSettings. Use the ThroughputSetting resource when retrieving offer details. */
@ -1235,10 +1257,6 @@ export interface SqlDatabaseResource {
export interface SqlContainerResource { export interface SqlContainerResource {
/* Name of the Cosmos DB SQL container */ /* Name of the Cosmos DB SQL container */
id: string; id: string;
vectorEmbeddingPolicy?: VectorEmbeddingPolicy;
fullTextPolicy?: FullTextPolicy;
/* The configuration of the indexing policy. By default, the indexing is automatic for all document paths within the container */ /* The configuration of the indexing policy. By default, the indexing is automatic for all document paths within the container */
indexingPolicy?: IndexingPolicy; indexingPolicy?: IndexingPolicy;
@ -1269,39 +1287,9 @@ export interface SqlContainerResource {
/* List of computed properties */ /* List of computed properties */
computedProperties?: ComputedProperty[]; computedProperties?: ComputedProperty[];
}
export interface VectorEmbeddingPolicy { /* The vector embedding policy for the container. */
vectorEmbeddings: VectorEmbedding[]; vectorEmbeddingPolicy?: VectorEmbeddingPolicy;
}
export interface VectorEmbedding {
path?: string;
dataType?: string;
dimensions?: number;
distanceFunction?: string;
}
export interface FullTextPolicy {
/**
* The default language for the full text .
*/
defaultLanguage: string;
/**
* The paths to be indexed for full text search.
*/
fullTextPaths: FullTextPath[];
}
export interface FullTextPath {
/**
* The path to be indexed for full text search.
*/
path: string;
/**
* The language for the full text path.
*/
language: string;
} }
/* Cosmos DB indexing policy */ /* Cosmos DB indexing policy */
@ -1323,19 +1311,14 @@ export interface IndexingPolicy {
/* List of spatial specifics */ /* List of spatial specifics */
spatialIndexes?: SpatialSpec[]; spatialIndexes?: SpatialSpec[];
/* List of paths to include in the vector indexing */
vectorIndexes?: VectorIndex[]; vectorIndexes?: VectorIndex[];
fullTextIndexes?: FullTextIndex[];
} }
export interface VectorIndex { /* Cosmos DB Vector Embedding Policy */
path?: string; export interface VectorEmbeddingPolicy {
type?: string; /* List of vector embeddings */
} vectorEmbeddings?: VectorEmbedding[];
export interface FullTextIndex {
/** The path in the JSON document to index. */
path: string;
} }
/* undocumented */ /* undocumented */
@ -1363,6 +1346,28 @@ export interface Indexes {
kind?: "Hash" | "Range" | "Spatial"; kind?: "Hash" | "Range" | "Spatial";
} }
/* undocumented */
export interface VectorIndex {
/* The path to the vector field in the document. */
path: string;
/* The index type of the vector. Currently, flat, diskANN, and quantizedFlat are supported. */
type: "flat" | "diskANN" | "quantizedFlat";
}
/* Represents a vector embedding. A vector embedding is used to define a vector field in the documents. */
export interface VectorEmbedding {
/* The path to the vector field in the document. */
path: string;
/* Indicates the data type of vector. */
dataType: "float32" | "uint8" | "int8";
/* The distance function to use for distance calculation in between vectors. */
distanceFunction: "euclidean" | "cosine" | "dotproduct";
/* The number of dimensions in the vector. */
dimensions: number;
}
/* List of composite path */ /* List of composite path */
export type CompositePathList = CompositePath[]; export type CompositePathList = CompositePath[];
@ -1688,6 +1693,28 @@ export interface Capacity {
totalThroughputLimit?: number; totalThroughputLimit?: number;
} }
/* Indicates the capacity mode of the account. */
export type CapacityMode = "None" | "Provisioned" | "Serverless";
/* The transition state information related capacity mode change with update request. */
export interface CapacityModeChangeTransitionState {
/* The transition status of capacity mode. */
capacityModeTransitionStatus?: "Invalid" | "Initialized" | "InProgress" | "Completed" | "Failed";
/* Indicates the current capacity mode of the account. */
currentCapacityMode?: "None" | "Provisioned" | "Serverless";
/* Indicates the previous capacity mode of the account before successful transition. */
previousCapacityMode?: "None" | "Provisioned" | "Serverless";
/* Begin time in UTC of the capacity mode change. */
readonly capacityModeTransitionBeginTimestamp?: string;
/* End time in UTC of the capacity mode change. */
readonly capacityModeTransitionEndTimestamp?: string;
/* End time in UTC of the last successful capacity mode change. */
readonly capacityModeLastSuccessfulTransitionEndTimestamp?: string;
}
/* Tags are a list of key-value pairs that describe the resource. These tags can be used in viewing and grouping this resource (across resource groups). A maximum of 15 tags can be provided for a resource. Each tag must have a key no greater than 128 characters and value no greater than 256 characters. For example, the default experience for a template type is set with "defaultExperience": "Cassandra". Current "defaultExperience" values also include "Table", "Graph", "DocumentDB", and "MongoDB". */ /* Tags are a list of key-value pairs that describe the resource. These tags can be used in viewing and grouping this resource (across resource groups). A maximum of 15 tags can be provided for a resource. Each tag must have a key no greater than 128 characters and value no greater than 256 characters. For example, the default experience for a template type is set with "defaultExperience": "Cassandra". Current "defaultExperience" values also include "Table", "Graph", "DocumentDB", and "MongoDB". */
export type Tags = { [key: string]: string }; export type Tags = { [key: string]: string };
@ -1953,8 +1980,8 @@ export type PublicNetworkAccess = "Enabled" | "Disabled" | "SecuredByPerimeter";
/* undocumented */ /* undocumented */
export interface ApiProperties { export interface ApiProperties {
/* Describes the ServerVersion of an a MongoDB account. */ /* Describes the version of the MongoDB account. */
serverVersion?: "3.2" | "3.6" | "4.0" | "4.2"; serverVersion?: "3.2" | "3.6" | "4.0" | "4.2" | "5.0" | "6.0" | "7.0";
} }
/* Analytical storage specific properties. */ /* Analytical storage specific properties. */

View File

@ -16,13 +16,13 @@ Results of this file should be checked into the repo.
*/ */
// CHANGE THESE VALUES TO GENERATE NEW CLIENTS // CHANGE THESE VALUES TO GENERATE NEW CLIENTS
const version = "2024-02-15-preview"; const version = "2024-12-01-preview";
/* The following are legal options for resourceName but you generally will only use cosmos-db: /* The following are legal options for resourceName but you generally will only use cosmos:
"cosmos-db" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" | "cosmos" | "managedCassandra" | "mongorbac" | "notebook" | "privateEndpointConnection" | "privateLinkResources" |
"rbac" | "restorable" | "services" | "dataTransferService" "rbac" | "restorable" | "services" | "dataTransferService"
*/ */
const githubResourceName = "cosmos-db"; const githubResourceName = "cosmos-db";
const deResourceName = "cosmos-db"; const deResourceName = "cosmos";
const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/${version}/${githubResourceName}.json`; const schemaURL = `https://raw.githubusercontent.com/Azure/azure-rest-api-specs/main/specification/cosmos-db/resource-manager/Microsoft.DocumentDB/preview/${version}/${githubResourceName}.json`;
const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${deResourceName}`); const outputDir = path.join(__dirname, `../../src/Utils/arm/generatedClients/${deResourceName}`);