diff --git a/src/Common/dataAccess/updateOffer.ts b/src/Common/dataAccess/updateOffer.ts index 4d26ca68d..fde4e6814 100644 --- a/src/Common/dataAccess/updateOffer.ts +++ b/src/Common/dataAccess/updateOffer.ts @@ -39,7 +39,10 @@ import { migrateTableToManualThroughput, updateTableThroughput, } from "../../Utils/arm/generatedClients/cosmos/tableResources"; -import { ThroughputSettingsUpdateParameters } from "../../Utils/arm/generatedClients/cosmos/types"; +import { + ThroughputSettingsGetResults, + ThroughputSettingsUpdateParameters, +} from "../../Utils/arm/generatedClients/cosmos/types"; import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils"; import { HttpHeaders } from "../Constants"; import { client } from "../CosmosClient"; @@ -146,23 +149,28 @@ const updateSqlContainerOffer = async (params: UpdateOfferParams): Promise const { subscriptionId, resourceGroup, databaseAccount } = userContext; const accountName = databaseAccount.name; + let updatedOffer: ThroughputSettingsGetResults; + if (params.migrateToAutoPilot) { - await migrateSqlContainerToAutoscale( + updatedOffer = (await migrateSqlContainerToAutoscale( subscriptionId, resourceGroup, accountName, params.databaseId, params.collectionId, - ); + )) as ThroughputSettingsGetResults; + params.autopilotThroughput = updatedOffer.properties?.resource?.autoscaleSettings?.maxThroughput; } else if (params.migrateToManual) { - await migrateSqlContainerToManualThroughput( + updatedOffer = (await migrateSqlContainerToManualThroughput( subscriptionId, resourceGroup, accountName, params.databaseId, params.collectionId, - ); - } else { + )) as ThroughputSettingsGetResults; + params.manualThroughput = updatedOffer.properties?.resource?.throughput; + } + if (params.throughputBuckets || !(params.migrateToAutoPilot || params.migrateToManual)) { const body: ThroughputSettingsUpdateParameters = createUpdateOfferBody(params); await updateSqlContainerThroughput( subscriptionId, diff --git a/src/Explorer/Controls/Settings/SettingsComponent.tsx b/src/Explorer/Controls/Settings/SettingsComponent.tsx index 3230f9b14..c9ab6f3c5 100644 --- a/src/Explorer/Controls/Settings/SettingsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsComponent.tsx @@ -106,6 +106,7 @@ export interface SettingsComponentState { changeFeedPolicyBaseline: ChangeFeedPolicyState; isSubSettingsSaveable: boolean; isSubSettingsDiscardable: boolean; + isThroughputBucketsSaveable: boolean; vectorEmbeddingPolicy: DataModels.VectorEmbeddingPolicy; vectorEmbeddingPolicyBaseline: DataModels.VectorEmbeddingPolicy; @@ -179,7 +180,9 @@ export class SettingsComponent extends React.Component this.setState({ indexingPolicyContent: newIndexingPolicy }); + private onThroughputBucketsSaveableChange = (isSaveable: boolean): void => { + this.setState({ isThroughputBucketsSaveable: isSaveable }); + }; + private resetShouldDiscardContainerPolicies = (): void => this.setState({ shouldDiscardContainerPolicies: false }); private resetShouldDiscardIndexingPolicy = (): void => this.setState({ shouldDiscardIndexingPolicy: false }); @@ -1053,7 +1062,8 @@ export class SettingsComponent extends React.Component void; + onThroughputBucketsSaveableChange: (isSaveable: boolean) => void; throughputError?: string; } interface ScaleComponentState { isThroughputSaveable: boolean; - isBucketsSaveable: boolean; + isThroughputBucketsSaveable: boolean; isThroughputDiscardable: boolean; - isBucketsDiscardable: boolean; + isThroughputBucketsDiscardable: boolean; } export class ScaleComponent extends React.Component { @@ -62,9 +63,9 @@ export class ScaleComponent extends React.Component { - const isSaveable = this.state.isThroughputSaveable || this.state.isBucketsSaveable; - const isDiscardable = this.state.isThroughputDiscardable || this.state.isBucketsDiscardable; + const isSaveable = this.state.isThroughputSaveable + ? this.state.isThroughputDiscardable || this.state.isThroughputBucketsSaveable + : this.state.isThroughputBucketsSaveable; + const isDiscardable = this.state.isThroughputDiscardable || this.state.isThroughputBucketsDiscardable; this.props.onScaleSaveableChange(isSaveable); + this.props.onThroughputBucketsSaveableChange(this.state.isThroughputBucketsSaveable); this.props.onScaleDiscardableChange(isDiscardable); }, ); @@ -209,12 +212,12 @@ export class ScaleComponent extends React.Component { - this.updateScaleSettingsState({ isBucketsSaveable: isSaveable }); + private handleThroughputBucketsSaveableChange = (isSaveable: boolean) => { + this.updateScaleSettingsState({ isThroughputBucketsSaveable: isSaveable }); }; - private handleBucketsDiscardableChange = (isDiscardable: boolean) => { - this.updateScaleSettingsState({ isBucketsDiscardable: isDiscardable }); + private handleThroughputBucketsDiscardableChange = (isDiscardable: boolean) => { + this.updateScaleSettingsState({ isThroughputBucketsDiscardable: isDiscardable }); }; public render(): JSX.Element { @@ -232,13 +235,13 @@ export class ScaleComponent extends React.Component{this.getInitialNotificationElement()} )} {!this.isAutoScaleEnabled() && {this.getThroughputInputComponent()}} - {this.props.enableThroughputBuckets && !this.props.isAutoPilotSelected && ( + {this.props.enableThroughputBuckets && ( )} diff --git a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent.tsx b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent.tsx index 13b72f0ad..ed3931c2b 100644 --- a/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent.tsx +++ b/src/Explorer/Controls/Settings/SettingsSubComponents/ThroughputInputComponents/ThroughputBucketsComponent.tsx @@ -1,4 +1,4 @@ -import { Icon, Label, Slider, Stack, TextField } from "@fluentui/react"; +import { Label, Slider, Stack, TextField, Toggle } from "@fluentui/react"; import { ThroughputBucket } from "Contracts/DataModels"; import React, { FC, useEffect, useState } from "react"; import { isDirty } from "../../SettingsUtils"; @@ -26,7 +26,16 @@ export const ThroughputBucketsComponent: FC = ( onDiscardableChange, }) => { const getThroughputBuckets = (buckets: ThroughputBucket[]): ThroughputBucket[] => { - return DEFAULT_BUCKETS.map( + if (!buckets || buckets.length === 0) { + return DEFAULT_BUCKETS; + } + const maxBuckets = Math.max(DEFAULT_BUCKETS.length, buckets.length); + const adjustedDefaultBuckets = Array.from({ length: maxBuckets }, (_, i) => ({ + id: i + 1, + maxThroughputPercentage: 100, + })); + + return adjustedDefaultBuckets.map( (defaultBucket) => buckets?.find((bucket) => bucket.id === defaultBucket.id) || defaultBucket, ); }; @@ -54,9 +63,13 @@ export const ThroughputBucketsComponent: FC = ( settingsChanged && onBucketsChange(updatedBuckets); }; + const onToggle = (id: number, checked: boolean) => { + handleBucketChange(id, checked ? 50 : 100); + }; + return ( - + {throughputBuckets?.map((bucket) => ( @@ -67,8 +80,9 @@ export const ThroughputBucketsComponent: FC = ( value={bucket.maxThroughputPercentage} onChange={(newValue) => handleBucketChange(bucket.id, newValue)} showValue={false} - label={`Bucket ${bucket.id}`} + label={`Group ${bucket.id}${bucket.id === 1 ? " (Data Explorer Query Bucket)" : ""}`} styles={{ root: { flex: 2, maxWidth: 400 } }} + disabled={bucket.maxThroughputPercentage === 100} /> = ( styles={{ fieldGroup: { width: 80 }, }} + disabled={bucket.maxThroughputPercentage === 100} /> - {bucket.id === 1 && ( + onToggle(bucket.id, checked)} + styles={{ root: { marginBottom: 0 }, text: { fontSize: 12 } }} + > + {/* {bucket.id === 1 && ( Data Explorer Query Bucket - )} + )} */} ))}