Update autoscale throughput limits (#1229)

* Change minimum autoscale throughput and default autoscale throughput for free tier account to 1000

* Fix unit tests

* Update snapshot

* Fix cassandra add collection panel

* Address comments

* Add feature flag/flight

* Remove console.log
This commit is contained in:
victor-meng 2022-02-25 18:21:58 -08:00 committed by GitHub
parent 7a809cd2bc
commit 605117c62d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 57 additions and 19 deletions

View File

@ -99,6 +99,7 @@ export class Flights {
public static readonly PhoenixNotebooks = "phoenixnotebooks"; public static readonly PhoenixNotebooks = "phoenixnotebooks";
public static readonly PhoenixFeatures = "phoenixfeatures"; public static readonly PhoenixFeatures = "phoenixfeatures";
public static readonly NotebooksDownBanner = "notebooksdownbanner"; public static readonly NotebooksDownBanner = "notebooksdownbanner";
public static readonly FreeTierAutoscaleThroughput = "freetierautoscalethroughput";
} }
export class AfecFeatures { export class AfecFeatures {

View File

@ -19,7 +19,7 @@ import { Action, ActionModifiers } from "../../../../../Shared/Telemetry/Telemet
import * as TelemetryProcessor from "../../../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../../../UserContext"; import { userContext } from "../../../../../UserContext";
import * as AutoPilotUtils from "../../../../../Utils/AutoPilotUtils"; import * as AutoPilotUtils from "../../../../../Utils/AutoPilotUtils";
import { minAutoPilotThroughput } from "../../../../../Utils/AutoPilotUtils"; import { autoPilotThroughput1K, autoPilotThroughput4K } from "../../../../../Utils/AutoPilotUtils";
import { calculateEstimateNumber, usageInGB } from "../../../../../Utils/PricingUtils"; import { calculateEstimateNumber, usageInGB } from "../../../../../Utils/PricingUtils";
import { Int32 } from "../../../../Panes/Tables/Validators/EntityPropertyValidationCommon"; import { Int32 } from "../../../../Panes/Tables/Validators/EntityPropertyValidationCommon";
import { import {
@ -540,7 +540,7 @@ export class ThroughputInputAutoPilotV3Component extends React.Component<
step={AutoPilotUtils.autoPilotIncrementStep} step={AutoPilotUtils.autoPilotIncrementStep}
value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()} value={this.overrideWithProvisionedThroughputSettings() ? "" : this.props.maxAutoPilotThroughput?.toString()}
onChange={this.onAutoPilotThroughputChange} onChange={this.onAutoPilotThroughputChange}
min={minAutoPilotThroughput} min={userContext.features.freetierAutoscaleThroughput ? autoPilotThroughput1K : autoPilotThroughput4K}
errorMessage={this.props.throughputError} errorMessage={this.props.throughputError}
/> />
{!this.overrideWithProvisionedThroughputSettings() && this.getAutoPilotUsageCost()} {!this.overrideWithProvisionedThroughputSettings() && this.getAutoPilotUsageCost()}

View File

@ -5,6 +5,7 @@ const props = {
isDatabase: false, isDatabase: false,
showFreeTierExceedThroughputTooltip: true, showFreeTierExceedThroughputTooltip: true,
isSharded: true, isSharded: true,
isFreeTier: false,
setThroughputValue: () => jest.fn(), setThroughputValue: () => jest.fn(),
setIsAutoscale: () => jest.fn(), setIsAutoscale: () => jest.fn(),
setIsThroughputCapExceeded: () => jest.fn(), setIsThroughputCapExceeded: () => jest.fn(),

View File

@ -14,6 +14,7 @@ import "./ThroughputInput.less";
export interface ThroughputInputProps { export interface ThroughputInputProps {
isDatabase: boolean; isDatabase: boolean;
isSharded: boolean; isSharded: boolean;
isFreeTier: boolean;
showFreeTierExceedThroughputTooltip: boolean; showFreeTierExceedThroughputTooltip: boolean;
setThroughputValue: (throughput: number) => void; setThroughputValue: (throughput: number) => void;
setIsAutoscale: (isAutoscale: boolean) => void; setIsAutoscale: (isAutoscale: boolean) => void;
@ -23,15 +24,20 @@ export interface ThroughputInputProps {
export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
isDatabase, isDatabase,
isSharded,
isFreeTier,
showFreeTierExceedThroughputTooltip, showFreeTierExceedThroughputTooltip,
setThroughputValue, setThroughputValue,
setIsAutoscale, setIsAutoscale,
setIsThroughputCapExceeded, setIsThroughputCapExceeded,
isSharded,
onCostAcknowledgeChange, onCostAcknowledgeChange,
}: ThroughputInputProps) => { }: ThroughputInputProps) => {
const [isAutoscaleSelected, setIsAutoScaleSelected] = useState<boolean>(true); const [isAutoscaleSelected, setIsAutoScaleSelected] = useState<boolean>(true);
const [throughput, setThroughput] = useState<number>(AutoPilotUtils.minAutoPilotThroughput); const [throughput, setThroughput] = useState<number>(
isFreeTier && userContext.features.freetierAutoscaleThroughput
? AutoPilotUtils.autoPilotThroughput1K
: AutoPilotUtils.autoPilotThroughput4K
);
const [isCostAcknowledged, setIsCostAcknowledged] = useState<boolean>(false); const [isCostAcknowledged, setIsCostAcknowledged] = useState<boolean>(false);
const [throughputError, setThroughputError] = useState<string>(""); const [throughputError, setThroughputError] = useState<string>("");
const [totalThroughputUsed, setTotalThroughputUsed] = useState<number>(0); const [totalThroughputUsed, setTotalThroughputUsed] = useState<number>(0);
@ -151,11 +157,15 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
const handleOnChangeMode = (event: React.ChangeEvent<HTMLInputElement>, mode: string): void => { const handleOnChangeMode = (event: React.ChangeEvent<HTMLInputElement>, mode: string): void => {
if (mode === "Autoscale") { if (mode === "Autoscale") {
setThroughput(AutoPilotUtils.minAutoPilotThroughput); const defaultThroughput =
isFreeTier && userContext.features.freetierAutoscaleThroughput
? AutoPilotUtils.autoPilotThroughput1K
: AutoPilotUtils.autoPilotThroughput4K;
setThroughput(defaultThroughput);
setIsAutoScaleSelected(true); setIsAutoScaleSelected(true);
setThroughputValue(AutoPilotUtils.minAutoPilotThroughput); setThroughputValue(defaultThroughput);
setIsAutoscale(true); setIsAutoscale(true);
checkThroughputCap(AutoPilotUtils.minAutoPilotThroughput); checkThroughputCap(defaultThroughput);
} else { } else {
setThroughput(SharedConstants.CollectionCreation.DefaultCollectionRUs400); setThroughput(SharedConstants.CollectionCreation.DefaultCollectionRUs400);
setIsAutoScaleSelected(false); setIsAutoScaleSelected(false);
@ -226,7 +236,11 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
}} }}
onChange={(event, newInput?: string) => onThroughputValueChange(newInput)} onChange={(event, newInput?: string) => onThroughputValueChange(newInput)}
step={AutoPilotUtils.autoPilotIncrementStep} step={AutoPilotUtils.autoPilotIncrementStep}
min={AutoPilotUtils.minAutoPilotThroughput} min={
userContext.features.freetierAutoscaleThroughput
? AutoPilotUtils.autoPilotThroughput1K
: AutoPilotUtils.autoPilotThroughput4K
}
value={throughput.toString()} value={throughput.toString()}
aria-label="Max request units per second" aria-label="Max request units per second"
required={true} required={true}

View File

@ -3,6 +3,7 @@
exports[`ThroughputInput Pane should render Default properly 1`] = ` exports[`ThroughputInput Pane should render Default properly 1`] = `
<ThroughputInput <ThroughputInput
isDatabase={false} isDatabase={false}
isFreeTier={false}
isSharded={true} isSharded={true}
onCostAcknowledgeChange={[Function]} onCostAcknowledgeChange={[Function]}
setIsAutoscale={[Function]} setIsAutoscale={[Function]}

View File

@ -249,6 +249,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated} showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated}
isDatabase={true} isDatabase={true}
isSharded={this.state.isSharded} isSharded={this.state.isSharded}
isFreeTier={this.isFreeTierAccount()}
setThroughputValue={(throughput: number) => (this.newDatabaseThroughput = throughput)} setThroughputValue={(throughput: number) => (this.newDatabaseThroughput = throughput)}
setIsAutoscale={(isAutoscale: boolean) => (this.isNewDatabaseAutoscale = isAutoscale)} setIsAutoscale={(isAutoscale: boolean) => (this.isNewDatabaseAutoscale = isAutoscale)}
setIsThroughputCapExceeded={(isThroughputCapExceeded: boolean) => setIsThroughputCapExceeded={(isThroughputCapExceeded: boolean) =>
@ -483,6 +484,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated} showFreeTierExceedThroughputTooltip={this.isFreeTierAccount() && !isFirstResourceCreated}
isDatabase={false} isDatabase={false}
isSharded={this.state.isSharded} isSharded={this.state.isSharded}
isFreeTier={this.isFreeTierAccount()}
setThroughputValue={(throughput: number) => (this.collectionThroughput = throughput)} setThroughputValue={(throughput: number) => (this.collectionThroughput = throughput)}
setIsAutoscale={(isAutoscale: boolean) => (this.isCollectionAutoscale = isAutoscale)} setIsAutoscale={(isAutoscale: boolean) => (this.isCollectionAutoscale = isAutoscale)}
setIsThroughputCapExceeded={(isThroughputCapExceeded: boolean) => setIsThroughputCapExceeded={(isThroughputCapExceeded: boolean) =>

View File

@ -146,9 +146,10 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
// TODO add feature flag that disables validation for customers with custom accounts // TODO add feature flag that disables validation for customers with custom accounts
if (isAutoscaleSelected) { if (isAutoscaleSelected) {
if (!AutoPilotUtils.isValidAutoPilotThroughput(throughput)) { if (!AutoPilotUtils.isValidAutoPilotThroughput(throughput)) {
setFormErrors( const minAutoPilotThroughput = userContext.features.freetierAutoscaleThroughput
`Please enter a value greater than ${AutoPilotUtils.minAutoPilotThroughput} for autopilot throughput` ? AutoPilotUtils.autoPilotThroughput1K
); : AutoPilotUtils.autoPilotThroughput4K;
setFormErrors(`Please enter a value greater than ${minAutoPilotThroughput} for autopilot throughput`);
return false; return false;
} }
} }
@ -241,6 +242,7 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()} showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()}
isDatabase={true} isDatabase={true}
isSharded={databaseCreateNewShared} isSharded={databaseCreateNewShared}
isFreeTier={isFreeTierAccount}
setThroughputValue={(newThroughput: number) => (throughput = newThroughput)} setThroughputValue={(newThroughput: number) => (throughput = newThroughput)}
setIsAutoscale={(isAutoscale: boolean) => (isAutoscaleSelected = isAutoscale)} setIsAutoscale={(isAutoscale: boolean) => (isAutoscaleSelected = isAutoscale)}
setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)} setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)}

View File

@ -262,6 +262,7 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
} }
isDatabase isDatabase
isSharded isSharded
isFreeTier={isFreeTierAccount}
setThroughputValue={(throughput: number) => (newKeySpaceThroughput = throughput)} setThroughputValue={(throughput: number) => (newKeySpaceThroughput = throughput)}
setIsAutoscale={(isAutoscale: boolean) => (isNewKeySpaceAutoscale = isAutoscale)} setIsAutoscale={(isAutoscale: boolean) => (isNewKeySpaceAutoscale = isAutoscale)}
setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)} setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)}
@ -335,6 +336,7 @@ export const CassandraAddCollectionPane: FunctionComponent<CassandraAddCollectio
showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()} showFreeTierExceedThroughputTooltip={isFreeTierAccount && !useDatabases.getState().isFirstResourceCreated()}
isDatabase={false} isDatabase={false}
isSharded isSharded
isFreeTier={isFreeTierAccount}
setThroughputValue={(throughput: number) => (tableThroughput = throughput)} setThroughputValue={(throughput: number) => (tableThroughput = throughput)}
setIsAutoscale={(isAutoscale: boolean) => (isTableAutoscale = isAutoscale)} setIsAutoscale={(isAutoscale: boolean) => (isTableAutoscale = isAutoscale)}
setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)} setIsThroughputCapExceeded={(isCapExceeded: boolean) => setIsThroughputCapExceeded(isCapExceeded)}

View File

@ -1,4 +1,5 @@
export type Features = { export type Features = {
// set only via feature flags
readonly canExceedMaximumValue: boolean; readonly canExceedMaximumValue: boolean;
readonly cosmosdb: boolean; readonly cosmosdb: boolean;
readonly enableChangeFeedPolicy: boolean; readonly enableChangeFeedPolicy: boolean;
@ -8,12 +9,6 @@ export type Features = {
readonly enableReactPane: boolean; readonly enableReactPane: boolean;
readonly enableRightPanelV2: boolean; readonly enableRightPanelV2: boolean;
readonly enableSchema: boolean; readonly enableSchema: boolean;
autoscaleDefault: boolean;
partitionKeyDefault: boolean;
partitionKeyDefault2: boolean;
phoenixNotebooks: boolean;
phoenixFeatures: boolean;
notebooksDownBanner: boolean;
readonly enableSDKoperations: boolean; readonly enableSDKoperations: boolean;
readonly enableSpark: boolean; readonly enableSpark: boolean;
readonly enableTtl: boolean; readonly enableTtl: boolean;
@ -34,11 +29,22 @@ export type Features = {
readonly mongoProxyEndpoint?: string; readonly mongoProxyEndpoint?: string;
readonly mongoProxyAPIs?: string; readonly mongoProxyAPIs?: string;
readonly enableThroughputCap: boolean; readonly enableThroughputCap: boolean;
// can be set via both flight and feature flag
autoscaleDefault: boolean;
partitionKeyDefault: boolean;
partitionKeyDefault2: boolean;
phoenixNotebooks: boolean;
phoenixFeatures: boolean;
notebooksDownBanner: boolean;
freetierAutoscaleThroughput: boolean;
}; };
export function extractFeatures(given = new URLSearchParams(window.location.search)): Features { export function extractFeatures(given = new URLSearchParams(window.location.search)): Features {
const downcased = new URLSearchParams(); const downcased = new URLSearchParams();
const set = (value: string, key: string) => downcased.set(key.toLowerCase(), value); const set = (value: string, key: string) => {
downcased.set(key.toLowerCase(), value);
};
const get = (key: string, defaultValue?: string) => const get = (key: string, defaultValue?: string) =>
downcased.get("feature." + key) ?? downcased.get(key) ?? defaultValue; downcased.get("feature." + key) ?? downcased.get(key) ?? defaultValue;
@ -86,6 +92,7 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
phoenixFeatures: "true" === get("phoenixfeatures"), phoenixFeatures: "true" === get("phoenixfeatures"),
notebooksDownBanner: "true" === get("notebooksDownBanner"), notebooksDownBanner: "true" === get("notebooksDownBanner"),
enableThroughputCap: "true" === get("enablethroughputcap"), enableThroughputCap: "true" === get("enablethroughputcap"),
freetierAutoscaleThroughput: "true" === get("freetierautoscalethroughput"),
}; };
} }

View File

@ -1,11 +1,16 @@
export const minAutoPilotThroughput = 4000; import { userContext } from "UserContext";
export const autoPilotThroughput1K = 1000;
export const autoPilotIncrementStep = 1000; export const autoPilotIncrementStep = 1000;
export const autoPilotThroughput4K = 4000;
export function isValidAutoPilotThroughput(maxThroughput: number): boolean { export function isValidAutoPilotThroughput(maxThroughput: number): boolean {
if (!maxThroughput) { if (!maxThroughput) {
return false; return false;
} }
const minAutoPilotThroughput = userContext.features.freetierAutoscaleThroughput
? autoPilotThroughput4K
: autoPilotThroughput1K;
if (maxThroughput < minAutoPilotThroughput) { if (maxThroughput < minAutoPilotThroughput) {
return false; return false;
} }

View File

@ -373,6 +373,9 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
if (inputs.flights.indexOf(Flights.NotebooksDownBanner) !== -1) { if (inputs.flights.indexOf(Flights.NotebooksDownBanner) !== -1) {
userContext.features.notebooksDownBanner = true; userContext.features.notebooksDownBanner = true;
} }
if (inputs.flights.indexOf(Flights.FreeTierAutoscaleThroughput) !== -1) {
userContext.features.freetierAutoscaleThroughput = true;
}
} }
} }