Merge remote-tracking branch 'origin/master' into flux-staging
commit
b9082de498
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
||||||
|
## v2.0.0-alpha.13 [unreleased]
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
### UI Improvements
|
||||||
|
|
||||||
|
1. [14157](https://github.com/influxdata/influxdb/pull/14157): Remove rendering bottleneck when streaming Flux responses
|
||||||
|
|
||||||
## v2.0.0-alpha.13 [2019-06-13]
|
## v2.0.0-alpha.13 [2019-06-13]
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -1088,8 +1088,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@influxdata/influx": {
|
"@influxdata/influx": {
|
||||||
"version": "github:influxdata/influxdb2-js#4bb7981498a2649391fbebdcaababafbf304f642",
|
"version": "0.3.5",
|
||||||
"from": "github:influxdata/influxdb2-js#dev",
|
"resolved": "https://registry.npmjs.org/@influxdata/influx/-/influx-0.3.5.tgz",
|
||||||
|
"integrity": "sha512-D2sCbBBGAkEtWyOibfiCCLT2qnmUoeME7GSrMJ3yyuxM/YtY+/gGmDZGIih3OTQld+VvDMgD78yWb66nk4GPVA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"axios": "^0.19.0"
|
"axios": "^0.19.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@influxdata/clockface": "0.0.13",
|
"@influxdata/clockface": "0.0.13",
|
||||||
"@influxdata/influx": "github:influxdata/influxdb2-js#dev",
|
"@influxdata/influx": "0.3.5",
|
||||||
"@influxdata/influxdb-templates": "influxdata/influxdb-templates",
|
"@influxdata/influxdb-templates": "influxdata/influxdb-templates",
|
||||||
"@influxdata/react-custom-scrollbars": "4.3.8",
|
"@influxdata/react-custom-scrollbars": "4.3.8",
|
||||||
"@influxdata/giraffe": "0.12.1",
|
"@influxdata/giraffe": "0.12.1",
|
||||||
|
|
|
@ -118,19 +118,19 @@ class DataListening extends PureComponent<OwnProps & WithRouterProps, State> {
|
||||||
const script = `from(bucket: "${bucket}")
|
const script = `from(bucket: "${bucket}")
|
||||||
|> range(start: -1m)`
|
|> range(start: -1m)`
|
||||||
|
|
||||||
let rowCount: number
|
let responseLength: number
|
||||||
let timePassed: number
|
let timePassed: number
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await runQuery(orgID, script).promise
|
const response = await runQuery(orgID, script).promise
|
||||||
rowCount = response.rowCount
|
responseLength = response.length
|
||||||
timePassed = Number(new Date()) - this.startTime
|
timePassed = Number(new Date()) - this.startTime
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.setState({loading: LoadingState.Error})
|
this.setState({loading: LoadingState.Error})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rowCount > 1) {
|
if (responseLength > 1) {
|
||||||
this.setState({loading: LoadingState.Done})
|
this.setState({loading: LoadingState.Done})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -139,6 +139,7 @@ class DataListening extends PureComponent<OwnProps & WithRouterProps, State> {
|
||||||
this.setState({loading: LoadingState.NotFound})
|
this.setState({loading: LoadingState.NotFound})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.intervalID = setTimeout(this.checkForData, FETCH_WAIT)
|
this.intervalID = setTimeout(this.checkForData, FETCH_WAIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,68 +1,36 @@
|
||||||
import Deferred from 'src/utils/Deferred'
|
|
||||||
import {getWindowVars} from 'src/variables/utils/getWindowVars'
|
import {getWindowVars} from 'src/variables/utils/getWindowVars'
|
||||||
import {buildVarsOption} from 'src/variables/utils/buildVarsOption'
|
import {buildVarsOption} from 'src/variables/utils/buildVarsOption'
|
||||||
import {client} from 'src/utils/api'
|
import {client} from 'src/utils/api'
|
||||||
|
|
||||||
import {File} from '@influxdata/influx'
|
import {
|
||||||
|
File,
|
||||||
|
CancellationError as ClientCancellationError,
|
||||||
|
} from '@influxdata/influx'
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import {WrappedCancelablePromise, CancellationError} from 'src/types/promises'
|
import {WrappedCancelablePromise, CancellationError} from 'src/types/promises'
|
||||||
import {VariableAssignment} from 'src/types/ast'
|
import {VariableAssignment} from 'src/types/ast'
|
||||||
|
|
||||||
const MAX_ROWS = 50000
|
const MAX_RESPONSE_CHARS = 50000 * 160
|
||||||
|
|
||||||
export interface ExecuteFluxQueryResult {
|
|
||||||
csv: string
|
|
||||||
didTruncate: boolean
|
|
||||||
rowCount: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export const runQuery = (
|
export const runQuery = (
|
||||||
orgID: string,
|
orgID: string,
|
||||||
query: string,
|
query: string,
|
||||||
extern?: File
|
extern?: File
|
||||||
): WrappedCancelablePromise<ExecuteFluxQueryResult> => {
|
): WrappedCancelablePromise<string> => {
|
||||||
const deferred = new Deferred()
|
const {promise, cancel} = client.queries.execute(orgID, query, {
|
||||||
|
extern,
|
||||||
const conn = client.queries.execute(orgID, query, extern)
|
limitChars: MAX_RESPONSE_CHARS,
|
||||||
|
|
||||||
let didTruncate = false
|
|
||||||
let rowCount = 0
|
|
||||||
let csv = ''
|
|
||||||
|
|
||||||
conn.stream.on('data', d => {
|
|
||||||
rowCount++
|
|
||||||
csv += d
|
|
||||||
|
|
||||||
if (rowCount < MAX_ROWS) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
didTruncate = true
|
|
||||||
conn.cancel()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
conn.stream.on('end', () => {
|
// Convert the client `CancellationError` to a UI `CancellationError`
|
||||||
const result: ExecuteFluxQueryResult = {
|
const wrappedPromise = promise.catch(error =>
|
||||||
csv,
|
error instanceof ClientCancellationError
|
||||||
didTruncate,
|
? Promise.reject(CancellationError)
|
||||||
rowCount,
|
: Promise.reject(error)
|
||||||
}
|
)
|
||||||
|
|
||||||
deferred.resolve(result)
|
return {promise: wrappedPromise, cancel}
|
||||||
})
|
|
||||||
|
|
||||||
conn.stream.on('error', err => {
|
|
||||||
deferred.reject(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
promise: deferred.promise,
|
|
||||||
cancel: () => {
|
|
||||||
conn.cancel()
|
|
||||||
deferred.reject(new CancellationError())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -86,7 +54,7 @@ export const executeQueryWithVars = (
|
||||||
orgID: string,
|
orgID: string,
|
||||||
query: string,
|
query: string,
|
||||||
variables?: VariableAssignment[]
|
variables?: VariableAssignment[]
|
||||||
): WrappedCancelablePromise<ExecuteFluxQueryResult> => {
|
): WrappedCancelablePromise<string> => {
|
||||||
let isCancelled = false
|
let isCancelled = false
|
||||||
let cancelExecution
|
let cancelExecution
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,7 @@ import {withRouter, WithRouterProps} from 'react-router'
|
||||||
import {fromFlux, FromFluxResult} from '@influxdata/giraffe'
|
import {fromFlux, FromFluxResult} from '@influxdata/giraffe'
|
||||||
|
|
||||||
// API
|
// API
|
||||||
import {
|
import {executeQueryWithVars} from 'src/shared/apis/query'
|
||||||
executeQueryWithVars,
|
|
||||||
ExecuteFluxQueryResult,
|
|
||||||
} from 'src/shared/apis/query'
|
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
import {checkQueryResult} from 'src/shared/utils/checkQueryResult'
|
import {checkQueryResult} from 'src/shared/utils/checkQueryResult'
|
||||||
|
@ -81,9 +78,7 @@ class TimeSeries extends Component<Props & WithRouterProps, State> {
|
||||||
|
|
||||||
public state: State = defaultState()
|
public state: State = defaultState()
|
||||||
|
|
||||||
private pendingResults: Array<
|
private pendingResults: Array<WrappedCancelablePromise<string>> = []
|
||||||
WrappedCancelablePromise<ExecuteFluxQueryResult>
|
|
||||||
> = []
|
|
||||||
|
|
||||||
public async componentDidMount() {
|
public async componentDidMount() {
|
||||||
this.reload()
|
this.reload()
|
||||||
|
@ -144,10 +139,8 @@ class TimeSeries extends Component<Props & WithRouterProps, State> {
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wait for new queries to complete
|
// Wait for new queries to complete
|
||||||
const results = await Promise.all(this.pendingResults.map(r => r.promise))
|
const files = await Promise.all(this.pendingResults.map(r => r.promise))
|
||||||
|
|
||||||
const duration = Date.now() - startTime
|
const duration = Date.now() - startTime
|
||||||
const files = results.map(r => r.csv)
|
|
||||||
const giraffeResult = fromFlux(files.join('\n\n'))
|
const giraffeResult = fromFlux(files.join('\n\n'))
|
||||||
|
|
||||||
files.forEach(checkQueryResult)
|
files.forEach(checkQueryResult)
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
import {get} from 'lodash'
|
import {get} from 'lodash'
|
||||||
|
|
||||||
// API
|
// API
|
||||||
import {
|
import {executeQueryWithVars} from 'src/shared/apis/query'
|
||||||
executeQueryWithVars,
|
|
||||||
ExecuteFluxQueryResult,
|
|
||||||
} from 'src/shared/apis/query'
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
import {refreshVariableValues, selectValue} from 'src/variables/actions'
|
import {refreshVariableValues, selectValue} from 'src/variables/actions'
|
||||||
|
@ -85,7 +82,7 @@ export const refreshTimeMachineVariableValues = () => async (
|
||||||
await dispatch(refreshVariableValues(contextID, variablesToRefresh))
|
await dispatch(refreshVariableValues(contextID, variablesToRefresh))
|
||||||
}
|
}
|
||||||
|
|
||||||
let pendingResults: Array<WrappedCancelablePromise<ExecuteFluxQueryResult>> = []
|
let pendingResults: Array<WrappedCancelablePromise<string>> = []
|
||||||
|
|
||||||
export const executeQueries = () => async (dispatch, getState: GetState) => {
|
export const executeQueries = () => async (dispatch, getState: GetState) => {
|
||||||
const {view, timeRange} = getActiveTimeMachine(getState())
|
const {view, timeRange} = getActiveTimeMachine(getState())
|
||||||
|
@ -115,10 +112,9 @@ export const executeQueries = () => async (dispatch, getState: GetState) => {
|
||||||
executeQueryWithVars(orgID, text, variableAssignments)
|
executeQueryWithVars(orgID, text, variableAssignments)
|
||||||
)
|
)
|
||||||
|
|
||||||
const results = await Promise.all(pendingResults.map(r => r.promise))
|
const files = await Promise.all(pendingResults.map(r => r.promise))
|
||||||
|
|
||||||
const duration = Date.now() - startTime
|
const duration = Date.now() - startTime
|
||||||
const files = results.map(r => r.csv)
|
|
||||||
|
|
||||||
files.forEach(checkQueryResult)
|
files.forEach(checkQueryResult)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import {get} from 'lodash'
|
import {get} from 'lodash'
|
||||||
|
|
||||||
// APIs
|
// APIs
|
||||||
import {runQuery, ExecuteFluxQueryResult} from 'src/shared/apis/query'
|
import {runQuery} from 'src/shared/apis/query'
|
||||||
import {parseResponse} from 'src/shared/parsing/flux/response'
|
import {parseResponse} from 'src/shared/parsing/flux/response'
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
|
@ -122,11 +122,8 @@ export function findValues({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function extractCol(
|
export function extractCol(resp: string, colName: string): string[] {
|
||||||
resp: ExecuteFluxQueryResult,
|
const tables = parseResponse(resp)
|
||||||
colName: string
|
|
||||||
): string[] {
|
|
||||||
const tables = parseResponse(resp.csv)
|
|
||||||
const data = get(tables, '0.data', [])
|
const data = get(tables, '0.data', [])
|
||||||
|
|
||||||
if (!data.length) {
|
if (!data.length) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ export class DefaultValueFetcher implements ValueFetcher {
|
||||||
|
|
||||||
const request = executeQueryWithVars(orgID, query, variables)
|
const request = executeQueryWithVars(orgID, query, variables)
|
||||||
|
|
||||||
const promise = request.promise.then(({csv}) => {
|
const promise = request.promise.then(csv => {
|
||||||
const values = extractValues(csv, prevSelection, defaultSelection)
|
const values = extractValues(csv, prevSelection, defaultSelection)
|
||||||
|
|
||||||
this.cache[key] = values
|
this.cache[key] = values
|
||||||
|
|
Loading…
Reference in New Issue