mirror of
https://github.com/apache/druid.git
synced 2025-02-23 03:03:02 +00:00
Fix UI datasources view edit action compaction (#10459)
Restore the web console's ability to view a datasource's compaction configuration via the "action" menu. Refactoring done in https://github.com/apache/druid/pull/10438 introduced a regression that always caused the default compaction configuration to be shown via the "action" menu instead. Regression test is added in e2e-tests/auto-compaction.spec.ts.
This commit is contained in:
parent
7385af0272
commit
ede25f1b45
@ -126,6 +126,11 @@ async function configureCompaction(
|
||||
) {
|
||||
const datasourcesOverview = new DatasourcesOverview(page, UNIFIED_CONSOLE_URL);
|
||||
await datasourcesOverview.setCompactionConfiguration(datasourceName, compactionConfig);
|
||||
|
||||
const savedCompactionConfig = await datasourcesOverview.getCompactionConfiguration(
|
||||
datasourceName,
|
||||
);
|
||||
expect(savedCompactionConfig).toEqual(compactionConfig);
|
||||
}
|
||||
|
||||
async function triggerCompaction() {
|
||||
|
@ -19,8 +19,10 @@
|
||||
import * as playwright from 'playwright-core';
|
||||
|
||||
import { clickButton } from '../../util/playwright';
|
||||
import { getLabeledInput } from '../../util/playwright';
|
||||
import { setLabeledInput } from '../../util/playwright';
|
||||
import { extractTable } from '../../util/table';
|
||||
import { readPartitionSpec } from '../load-data/config/partition';
|
||||
|
||||
import { CompactionConfig } from './compaction';
|
||||
import { Datasource } from './datasource';
|
||||
@ -42,6 +44,9 @@ enum DatasourceColumn {
|
||||
ACTIONS,
|
||||
}
|
||||
|
||||
const EDIT_COMPACTION_CONFIGURATION = 'Edit compaction configuration';
|
||||
const SKIP_OFFSET_FROM_LATEST = 'Skip offset from latest';
|
||||
|
||||
/**
|
||||
* Represents datasource overview tab.
|
||||
*/
|
||||
@ -80,10 +85,10 @@ export class DatasourcesOverview {
|
||||
): Promise<void> {
|
||||
await this.openEditActions(datasourceName);
|
||||
|
||||
await this.page.click('"Edit compaction configuration"');
|
||||
await this.page.click(`"${EDIT_COMPACTION_CONFIGURATION}"`);
|
||||
await setLabeledInput(
|
||||
this.page,
|
||||
'Skip offset from latest',
|
||||
SKIP_OFFSET_FROM_LATEST,
|
||||
compactionConfig.skipOffsetFromLatest,
|
||||
);
|
||||
await compactionConfig.partitionsSpec.apply(this.page);
|
||||
@ -91,6 +96,17 @@ export class DatasourcesOverview {
|
||||
await clickButton(this.page, 'Submit');
|
||||
}
|
||||
|
||||
async getCompactionConfiguration(datasourceName: string): Promise<CompactionConfig> {
|
||||
await this.openEditActions(datasourceName);
|
||||
|
||||
await this.page.click(`"${EDIT_COMPACTION_CONFIGURATION}"`);
|
||||
const skipOffsetFromLatest = await getLabeledInput(this.page, SKIP_OFFSET_FROM_LATEST);
|
||||
const partitionsSpec = await readPartitionSpec(this.page);
|
||||
|
||||
await clickButton(this.page, 'Close');
|
||||
return new CompactionConfig({ skipOffsetFromLatest, partitionsSpec: partitionsSpec! });
|
||||
}
|
||||
|
||||
private async openEditActions(datasourceName: string): Promise<void> {
|
||||
const datasources = await this.getDatasources();
|
||||
const index = datasources.findIndex(t => t.name === datasourceName);
|
||||
@ -100,6 +116,6 @@ export class DatasourcesOverview {
|
||||
|
||||
const editActions = await this.page.$$('span[icon=wrench]');
|
||||
editActions[index].click();
|
||||
await this.page.waitFor(5000);
|
||||
await this.page.waitFor('ul.bp3-menu');
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
import * as playwright from 'playwright-core';
|
||||
|
||||
import { selectSuggestibleInput } from '../../../util/playwright';
|
||||
import { getLabeledInput } from '../../../util/playwright';
|
||||
import { setLabeledInput } from '../../../util/playwright';
|
||||
|
||||
/* tslint:disable max-classes-per-file */
|
||||
@ -40,22 +41,49 @@ export interface PartitionsSpec {
|
||||
apply(page: playwright.Page): Promise<void>;
|
||||
}
|
||||
|
||||
export async function readPartitionSpec(page: playwright.Page): Promise<PartitionsSpec | null> {
|
||||
const type = await getLabeledInput(page, PARTITIONING_TYPE);
|
||||
switch (type) {
|
||||
case HashedPartitionsSpec.TYPE:
|
||||
return HashedPartitionsSpec.read(page);
|
||||
case SingleDimPartitionsSpec.TYPE:
|
||||
return SingleDimPartitionsSpec.read(page);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export class HashedPartitionsSpec implements PartitionsSpec {
|
||||
public static TYPE = 'hashed';
|
||||
private static NUM_SHARDS = 'Num shards';
|
||||
|
||||
readonly type: string;
|
||||
|
||||
static async read(page: playwright.Page): Promise<HashedPartitionsSpec> {
|
||||
const numShards = await getLabeledInputAsNumber(page, HashedPartitionsSpec.NUM_SHARDS);
|
||||
return new HashedPartitionsSpec({ numShards });
|
||||
}
|
||||
|
||||
constructor(props: HashedPartitionsSpecProps) {
|
||||
Object.assign(this, props);
|
||||
this.type = 'hashed';
|
||||
this.type = HashedPartitionsSpec.TYPE;
|
||||
}
|
||||
|
||||
async apply(page: playwright.Page): Promise<void> {
|
||||
await setLabeledInput(page, PARTITIONING_TYPE, this.type);
|
||||
if (this.numShards != null) {
|
||||
await setLabeledInput(page, 'Num shards', String(this.numShards));
|
||||
await setLabeledInput(page, HashedPartitionsSpec.NUM_SHARDS, String(this.numShards));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getLabeledInputAsNumber(
|
||||
page: playwright.Page,
|
||||
label: string,
|
||||
): Promise<number | null> {
|
||||
const valueString = await getLabeledInput(page, label);
|
||||
return valueString === '' ? null : Number(valueString);
|
||||
}
|
||||
|
||||
interface HashedPartitionsSpecProps {
|
||||
readonly numShards: number | null;
|
||||
}
|
||||
@ -63,21 +91,58 @@ interface HashedPartitionsSpecProps {
|
||||
export interface HashedPartitionsSpec extends HashedPartitionsSpecProps {}
|
||||
|
||||
export class SingleDimPartitionsSpec implements PartitionsSpec {
|
||||
public static TYPE = 'single_dim';
|
||||
private static PARTITION_DIMENSION = 'Partition dimension';
|
||||
private static TARGET_ROWS_PER_SEGMENT = 'Target rows per segment';
|
||||
private static MAX_ROWS_PER_SEGMENT = 'Max rows per segment';
|
||||
|
||||
readonly type: string;
|
||||
|
||||
static async read(page: playwright.Page): Promise<SingleDimPartitionsSpec> {
|
||||
const partitionDimension = await getLabeledInput(
|
||||
page,
|
||||
SingleDimPartitionsSpec.PARTITION_DIMENSION,
|
||||
);
|
||||
const targetRowsPerSegment = await getLabeledInputAsNumber(
|
||||
page,
|
||||
SingleDimPartitionsSpec.TARGET_ROWS_PER_SEGMENT,
|
||||
);
|
||||
const maxRowsPerSegment = await getLabeledInputAsNumber(
|
||||
page,
|
||||
SingleDimPartitionsSpec.MAX_ROWS_PER_SEGMENT,
|
||||
);
|
||||
return new SingleDimPartitionsSpec({
|
||||
partitionDimension,
|
||||
targetRowsPerSegment,
|
||||
maxRowsPerSegment,
|
||||
});
|
||||
}
|
||||
|
||||
constructor(props: SingleDimPartitionsSpecProps) {
|
||||
Object.assign(this, props);
|
||||
this.type = 'single_dim';
|
||||
this.type = SingleDimPartitionsSpec.TYPE;
|
||||
}
|
||||
|
||||
async apply(page: playwright.Page): Promise<void> {
|
||||
await selectSuggestibleInput(page, PARTITIONING_TYPE, this.type);
|
||||
await setLabeledInput(page, 'Partition dimension', this.partitionDimension);
|
||||
await setLabeledInput(
|
||||
page,
|
||||
SingleDimPartitionsSpec.PARTITION_DIMENSION,
|
||||
this.partitionDimension,
|
||||
);
|
||||
if (this.targetRowsPerSegment) {
|
||||
await setLabeledInput(page, 'Target rows per segment', String(this.targetRowsPerSegment));
|
||||
await setLabeledInput(
|
||||
page,
|
||||
SingleDimPartitionsSpec.TARGET_ROWS_PER_SEGMENT,
|
||||
String(this.targetRowsPerSegment),
|
||||
);
|
||||
}
|
||||
if (this.maxRowsPerSegment) {
|
||||
await setLabeledInput(page, 'Max rows per segment', String(this.maxRowsPerSegment));
|
||||
await setLabeledInput(
|
||||
page,
|
||||
SingleDimPartitionsSpec.MAX_ROWS_PER_SEGMENT,
|
||||
String(this.maxRowsPerSegment),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,13 @@ export async function createPage(browser: playwright.Browser): Promise<playwrigh
|
||||
return page;
|
||||
}
|
||||
|
||||
export async function getLabeledInput(page: playwright.Page, label: string): Promise<string> {
|
||||
return await page.$eval(
|
||||
`//*[text()="${label}"]/following-sibling::div//input`,
|
||||
el => (el as HTMLInputElement).value,
|
||||
);
|
||||
}
|
||||
|
||||
export async function setLabeledInput(
|
||||
page: playwright.Page,
|
||||
label: string,
|
||||
|
@ -1209,12 +1209,12 @@ GROUP BY 1`;
|
||||
width: ACTION_COLUMN_WIDTH,
|
||||
filterable: false,
|
||||
Cell: ({ value: datasource, original }) => {
|
||||
const { unused, rules, compaction } = original;
|
||||
const { unused, rules, compactionConfig } = original;
|
||||
const datasourceActions = this.getDatasourceActions(
|
||||
datasource,
|
||||
unused,
|
||||
rules,
|
||||
compaction,
|
||||
compactionConfig,
|
||||
);
|
||||
return (
|
||||
<ActionCell
|
||||
|
Loading…
x
Reference in New Issue
Block a user