add timeout to capabilities check (#8213)

This commit is contained in:
Vadim Ogievetsky 2019-08-01 08:37:02 -07:00 committed by Fangjin Yang
parent f0ecdfee30
commit a0f88868e3
5 changed files with 36 additions and 15 deletions

View File

@ -25,7 +25,7 @@ import { HashRouter, Route, Switch } from 'react-router-dom';
import { ExternalLink, HeaderActiveTab, HeaderBar, Loader } from './components'; import { ExternalLink, HeaderActiveTab, HeaderBar, Loader } from './components';
import { AppToaster } from './singletons/toaster'; import { AppToaster } from './singletons/toaster';
import { QueryManager } from './utils'; import { localStorageGet, LocalStorageKeys, QueryManager } from './utils';
import { DRUID_DOCS_API, DRUID_DOCS_SQL } from './variables'; import { DRUID_DOCS_API, DRUID_DOCS_SQL } from './variables';
import { import {
DatasourcesView, DatasourcesView,
@ -56,20 +56,27 @@ export class ConsoleApplication extends React.PureComponent<
ConsoleApplicationProps, ConsoleApplicationProps,
ConsoleApplicationState ConsoleApplicationState
> { > {
static MESSAGE_KEY = 'druid-console-message'; static STATUS_TIMEOUT = 2000;
static MESSAGE_DISMISSED = 'dismissed';
private capabilitiesQueryManager: QueryManager<null, Capabilities>; private capabilitiesQueryManager: QueryManager<null, Capabilities>;
static async discoverCapabilities(): Promise<Capabilities> { static async discoverCapabilities(): Promise<Capabilities> {
const capabilitiesOverride = localStorageGet(LocalStorageKeys.CAPABILITIES_OVERRIDE);
if (capabilitiesOverride) return capabilitiesOverride as Capabilities;
try { try {
await axios.post('/druid/v2/sql', { query: 'SELECT 1337' }); await axios.post(
'/druid/v2/sql',
{ query: 'SELECT 1337', context: { timeout: ConsoleApplication.STATUS_TIMEOUT } },
{ timeout: ConsoleApplication.STATUS_TIMEOUT },
);
} catch (e) { } catch (e) {
const { response } = e; const { response } = e;
if (response.status !== 405 || response.statusText !== 'Method Not Allowed') { if (response.status !== 405 || response.statusText !== 'Method Not Allowed') {
return 'working-with-sql'; // other failure return 'working-with-sql'; // other failure
} }
try { try {
await axios.get('/status'); await axios.get('/status', { timeout: ConsoleApplication.STATUS_TIMEOUT });
} catch (e) { } catch (e) {
return 'broken'; // total failure return 'broken'; // total failure
} }

View File

@ -321,3 +321,7 @@ export function downloadFile(text: string, type: string, filename: string): void
}); });
FileSaver.saveAs(blob, filename); FileSaver.saveAs(blob, filename);
} }
export function escapeSqlIdentifier(identifier: string): string {
return `"${identifier.replace(/"/g, '""')}"`;
}

View File

@ -17,6 +17,7 @@
*/ */
export const LocalStorageKeys = { export const LocalStorageKeys = {
CAPABILITIES_OVERRIDE: 'capabilities-override' as 'capabilities-override',
INGESTION_SPEC: 'ingestion-spec' as 'ingestion-spec', INGESTION_SPEC: 'ingestion-spec' as 'ingestion-spec',
DATASOURCE_TABLE_COLUMN_SELECTION: 'datasource-table-column-selection' as 'datasource-table-column-selection', DATASOURCE_TABLE_COLUMN_SELECTION: 'datasource-table-column-selection' as 'datasource-table-column-selection',
SEGMENT_TABLE_COLUMN_SELECTION: 'segment-table-column-selection' as 'segment-table-column-selection', SEGMENT_TABLE_COLUMN_SELECTION: 'segment-table-column-selection' as 'segment-table-column-selection',

View File

@ -37,6 +37,7 @@ import { AppToaster } from '../../singletons/toaster';
import { import {
addFilter, addFilter,
countBy, countBy,
escapeSqlIdentifier,
formatBytes, formatBytes,
formatNumber, formatNumber,
getDruidErrorMessage, getDruidErrorMessage,
@ -558,7 +559,7 @@ GROUP BY 1`;
{ {
icon: IconNames.APPLICATION, icon: IconNames.APPLICATION,
title: 'Query with SQL', title: 'Query with SQL',
onAction: () => goToQuery(`SELECT * FROM "${datasource}"`), onAction: () => goToQuery(`SELECT * FROM ${escapeSqlIdentifier(datasource)}`),
}, },
{ {
icon: IconNames.AUTOMATIC_UPDATES, icon: IconNames.AUTOMATIC_UPDATES,

View File

@ -21,7 +21,7 @@ import { IconNames } from '@blueprintjs/icons';
import React, { ChangeEvent } from 'react'; import React, { ChangeEvent } from 'react';
import { Loader } from '../../../components'; import { Loader } from '../../../components';
import { groupBy } from '../../../utils'; import { escapeSqlIdentifier, groupBy } from '../../../utils';
import { ColumnMetadata } from '../../../utils/column-metadata'; import { ColumnMetadata } from '../../../utils/column-metadata';
import './column-tree.scss'; import './column-tree.scss';
@ -159,13 +159,13 @@ export class ColumnTree extends React.PureComponent<ColumnTreeProps, ColumnTreeS
const tableSchema = selectedNode.label; const tableSchema = selectedNode.label;
let columns: string[]; let columns: string[];
if (nodeData.childNodes) { if (nodeData.childNodes) {
columns = nodeData.childNodes.map(child => String(child.label)); columns = nodeData.childNodes.map(child => escapeSqlIdentifier(String(child.label)));
} else { } else {
columns = ['*']; columns = ['*'];
} }
if (tableSchema === 'druid') { if (tableSchema === 'druid') {
onQueryStringChange(`SELECT ${columns.join(', ')} onQueryStringChange(`SELECT ${columns.join(', ')}
FROM "${nodeData.label}" FROM ${escapeSqlIdentifier(String(nodeData.label))}
WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY`); WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY`);
} else { } else {
onQueryStringChange(`SELECT ${columns.join(', ')} onQueryStringChange(`SELECT ${columns.join(', ')}
@ -176,23 +176,31 @@ FROM ${tableSchema}.${nodeData.label}`);
case 2: // Column case 2: // Column
const schemaNode = selectedNode; const schemaNode = selectedNode;
const columnSchema = schemaNode.label; const columnSchema = schemaNode.label;
const columnTable = schemaNode.childNodes ? schemaNode.childNodes[nodePath[0]].label : '?'; const columnTable = schemaNode.childNodes
? String(schemaNode.childNodes[nodePath[0]].label)
: '?';
if (columnSchema === 'druid') { if (columnSchema === 'druid') {
if (nodeData.icon === IconNames.TIME) { if (nodeData.icon === IconNames.TIME) {
onQueryStringChange(`SELECT TIME_FLOOR("${nodeData.label}", 'PT1H') AS "Time", COUNT(*) AS "Count" onQueryStringChange(`SELECT
FROM "${columnTable}" TIME_FLOOR(${escapeSqlIdentifier(String(nodeData.label))}, 'PT1H') AS "Time",
COUNT(*) AS "Count"
FROM ${escapeSqlIdentifier(columnTable)}
WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY
GROUP BY 1 GROUP BY 1
ORDER BY "Time" ASC`); ORDER BY "Time" ASC`);
} else { } else {
onQueryStringChange(`SELECT "${nodeData.label}", COUNT(*) AS "Count" onQueryStringChange(`SELECT
FROM "${columnTable}" "${nodeData.label}",
COUNT(*) AS "Count"
FROM ${escapeSqlIdentifier(columnTable)}
WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY WHERE "__time" >= CURRENT_TIMESTAMP - INTERVAL '1' DAY
GROUP BY 1 GROUP BY 1
ORDER BY "Count" DESC`); ORDER BY "Count" DESC`);
} }
} else { } else {
onQueryStringChange(`SELECT "${nodeData.label}", COUNT(*) AS "Count" onQueryStringChange(`SELECT
${escapeSqlIdentifier(String(nodeData.label))},
COUNT(*) AS "Count"
FROM ${columnSchema}.${columnTable} FROM ${columnSchema}.${columnTable}
GROUP BY 1 GROUP BY 1
ORDER BY "Count" DESC`); ORDER BY "Count" DESC`);