diff --git a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx index c5e107c8a7a..ea239bc3a26 100644 --- a/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx +++ b/web-console/src/views/workbench-view/max-tasks-button/max-tasks-button.tsx @@ -39,14 +39,28 @@ const TASK_ASSIGNMENT_DESCRIPTION: Record = { auto: `Use as few tasks as possible without exceeding 512 MiB or 10,000 files per task, unless exceeding these limits is necessary to stay within 'maxNumTasks'. When calculating the size of files, the weighted size is used, which considers the file format and compression format used if any. When file sizes cannot be determined through directory listing (for example: http), behaves the same as 'max'.`, }; +const DEFAULT_MAX_NUM_LABEL_FN = (maxNum: number) => { + if (maxNum === 2) return { text: formatInteger(maxNum), label: '(1 controller + 1 worker)' }; + return { text: formatInteger(maxNum), label: `(1 controller + max ${maxNum - 1} workers)` }; +}; + export interface MaxTasksButtonProps extends Omit { clusterCapacity: number | undefined; queryContext: QueryContext; changeQueryContext(queryContext: QueryContext): void; + menuHeader?: JSX.Element; + maxNumLabelFn?: (maxNum: number) => { text: string; label?: string }; } export const MaxTasksButton = function MaxTasksButton(props: MaxTasksButtonProps) { - const { clusterCapacity, queryContext, changeQueryContext, ...rest } = props; + const { + clusterCapacity, + queryContext, + changeQueryContext, + menuHeader, + maxNumLabelFn = DEFAULT_MAX_NUM_LABEL_FN, + ...rest + } = props; const [customMaxNumTasksDialogOpen, setCustomMaxNumTasksDialogOpen] = useState(false); const maxNumTasks = getMaxNumTasks(queryContext); @@ -68,6 +82,7 @@ export const MaxTasksButton = function MaxTasksButton(props: MaxTasksButtonProps position={Position.BOTTOM_LEFT} content={ + {menuHeader} {Boolean(fullClusterCapacity) && ( changeQueryContext(changeMaxNumTasks(queryContext, undefined))} /> )} - {shownMaxNumTaskOptions.map(m => ( - changeQueryContext(changeMaxNumTasks(queryContext, m))} - /> - ))} + {shownMaxNumTaskOptions.map(m => { + const { text, label } = maxNumLabelFn(m); + + return ( + changeQueryContext(changeMaxNumTasks(queryContext, m))} + /> + ); + })} Promise) | undefined; + maxTaskMenuHeader?: JSX.Element; + enginesLabelFn?: ComponentProps['enginesLabelFn']; + maxTaskLabelFn?: ComponentProps['maxTaskLabelFn']; } export const QueryTab = React.memo(function QueryTab(props: QueryTabProps) { @@ -98,6 +101,9 @@ export const QueryTab = React.memo(function QueryTab(props: QueryTabProps) { clusterCapacity, goToTask, getClusterCapacity, + maxTaskMenuHeader, + enginesLabelFn, + maxTaskLabelFn, } = props; const [alertElement, setAlertElement] = useState(); @@ -399,6 +405,9 @@ export const QueryTab = React.memo(function QueryTab(props: QueryTabProps) { queryEngines={queryEngines} clusterCapacity={clusterCapacity} moreMenu={runMoreMenu} + maxTaskMenuHeader={maxTaskMenuHeader} + enginesLabelFn={enginesLabelFn} + maxTaskLabelFn={maxTaskLabelFn} /> {executionState.isLoading() && ( = { ), }; +const DEFAULT_ENGINES_LABEL_FN = (engine: DruidEngine | undefined) => { + if (!engine) return { text: 'auto' }; + return { + text: engine, + label: engine === 'sql-msq-task' ? 'multi-stage-query' : undefined, + }; +}; + export interface RunPanelProps { query: WorkbenchQuery; onQueryChange(query: WorkbenchQuery): void; @@ -120,11 +128,25 @@ export interface RunPanelProps { queryEngines: DruidEngine[]; clusterCapacity: number | undefined; moreMenu?: JSX.Element; + maxTaskMenuHeader?: JSX.Element; + enginesLabelFn?: (engine: DruidEngine | undefined) => { text: string; label?: string }; + maxTaskLabelFn?: ComponentProps['maxNumLabelFn']; } export const RunPanel = React.memo(function RunPanel(props: RunPanelProps) { - const { query, onQueryChange, onRun, moreMenu, running, small, queryEngines, clusterCapacity } = - props; + const { + query, + onQueryChange, + onRun, + moreMenu, + running, + small, + queryEngines, + clusterCapacity, + maxTaskMenuHeader, + maxTaskLabelFn, + enginesLabelFn = DEFAULT_ENGINES_LABEL_FN, + } = props; const [editContextDialogOpen, setEditContextDialogOpen] = useState(false); const [editParametersDialogOpen, setEditParametersDialogOpen] = useState(false); const [customTimezoneDialogOpen, setCustomTimezoneDialogOpen] = useState(false); @@ -186,25 +208,11 @@ export const RunPanel = React.memo(function RunPanel(props: RunPanelProps) { useHotkeys(hotkeys); const queryEngine = query.engine; - function renderQueryEngineMenuItem(e: DruidEngine | undefined) { - return ( - onQueryChange(query.changeEngine(e))} - shouldDismissPopover={false} - /> - ); - } function changeQueryContext(queryContext: QueryContext) { onQueryChange(query.changeQueryContext(queryContext)); } - const availableEngines = ([undefined] as (DruidEngine | undefined)[]).concat(queryEngines); - function offsetOptions(): JSX.Element[] { const items: JSX.Element[] = []; @@ -231,6 +239,9 @@ export const RunPanel = React.memo(function RunPanel(props: RunPanelProps) { const intent = overloadWarning ? Intent.WARNING : undefined; const effectiveEngine = query.getEffectiveEngine(); + + const autoEngineLabel = enginesLabelFn(undefined); + return (