feat(ui): display notification when Flux response is truncated

pull/14551/head
Christopher Henn 2019-07-31 14:33:00 -07:00
parent e62fbe6242
commit 8a5dcd5707
4 changed files with 50 additions and 19 deletions

View File

@ -15,7 +15,7 @@ import {buildVarsOption} from 'src/variables/utils/buildVarsOption'
// Constants // Constants
import {RATE_LIMIT_ERROR_STATUS} from 'src/cloud/constants/index' import {RATE_LIMIT_ERROR_STATUS} from 'src/cloud/constants/index'
import {rateLimitReached} from 'src/shared/copy/notifications' import {rateLimitReached, resultTooLarge} from 'src/shared/copy/notifications'
import {RATE_LIMIT_ERROR_TEXT} from 'src/cloud/constants' import {RATE_LIMIT_ERROR_TEXT} from 'src/cloud/constants'
// Actions // Actions
@ -139,17 +139,24 @@ class TimeSeries extends Component<Props & WithRouterProps, State> {
this.pendingResults = queries.map(({text}) => { this.pendingResults = queries.map(({text}) => {
const windowVars = getWindowVars(text, variables) const windowVars = getWindowVars(text, variables)
const extern = buildVarsOption([...variables, ...windowVars]) const extern = buildVarsOption([...variables, ...windowVars])
return runQuery(orgID, text, extern) return runQuery(orgID, text, extern)
}) })
// Wait for new queries to complete // Wait for new queries to complete
const files = await Promise.all( const results = await Promise.all(this.pendingResults.map(r => r.promise))
this.pendingResults.map(r => r.promise.then(({csv}) => csv))
)
const duration = Date.now() - startTime const duration = Date.now() - startTime
const giraffeResult = fromFlux(files.join('\n\n'))
files.forEach(checkQueryResult) for (const result of results) {
checkQueryResult(result.csv)
if (result.didTruncate) {
notify(resultTooLarge(result.bytesRead))
}
}
const files = results.map(r => r.csv)
const giraffeResult = fromFlux(files.join('\n\n'))
this.setState({ this.setState({
giraffeResult, giraffeResult,

View File

@ -51,8 +51,8 @@ export const CLOUD_CHECKOUT_PATH = process.env.CLOUD_CHECKOUT_PATH
export const CLOUD_BILLING_PATH = process.env.CLOUD_BILLING_PATH export const CLOUD_BILLING_PATH = process.env.CLOUD_BILLING_PATH
export const FLUX_RESPONSE_BYTES_LIMIT = CLOUD export const FLUX_RESPONSE_BYTES_LIMIT = CLOUD
? 10 * 1024 * 1024 ? 10 * 1024 * 1024 // 10 MiB
: 100 * 1024 * 1024 : 100 * 1024 * 1024 // 100 MiB
export const VIS_SIG_DIGITS = 4 export const VIS_SIG_DIGITS = 4

View File

@ -1,16 +1,25 @@
// All copy for notifications should be stored here for easy editing // Libraries
// and ensuring stylistic consistency import {binaryPrefixFormatter} from '@influxdata/giraffe'
// Types
import {Notification} from 'src/types' import {Notification} from 'src/types'
import {NotificationStyle} from 'src/types/notifications' import {NotificationStyle} from 'src/types/notifications'
// Constants
import {FIVE_SECONDS, TEN_SECONDS, INFINITE} from 'src/shared/constants/index'
import {QUICKSTART_SCRAPER_TARGET_URL} from 'src/dataLoaders/constants/pluginConfigs'
const bytesFormatter = binaryPrefixFormatter({
suffix: 'B',
significantDigits: 2,
trimZeros: true,
})
type NotificationExcludingMessage = Pick< type NotificationExcludingMessage = Pick<
Notification, Notification,
Exclude<keyof Notification, 'message'> Exclude<keyof Notification, 'message'>
> >
import {FIVE_SECONDS, TEN_SECONDS, INFINITE} from 'src/shared/constants/index'
import {QUICKSTART_SCRAPER_TARGET_URL} from 'src/dataLoaders/constants/pluginConfigs'
const defaultErrorNotification: NotificationExcludingMessage = { const defaultErrorNotification: NotificationExcludingMessage = {
style: NotificationStyle.Error, style: NotificationStyle.Error,
icon: 'alert-triangle', icon: 'alert-triangle',
@ -58,6 +67,15 @@ export const sessionTimedOut = (): Notification => ({
message: 'Your session has timed out. Log in again to continue.', message: 'Your session has timed out. Log in again to continue.',
}) })
export const resultTooLarge = (bytesRead: number): Notification => ({
style: NotificationStyle.Error,
icon: 'triangle',
duration: FIVE_SECONDS,
message: `Large Flux response truncated to first ${bytesFormatter(
bytesRead
)}`,
})
// Onboarding notifications // Onboarding notifications
export const SetupSuccess: Notification = { export const SetupSuccess: Notification = {
...defaultSuccessNotification, ...defaultSuccessNotification,

View File

@ -8,7 +8,7 @@ import {refreshVariableValues, selectValue} from 'src/variables/actions'
import {notify} from 'src/shared/actions/notifications' import {notify} from 'src/shared/actions/notifications'
// Constants // Constants
import {rateLimitReached} from 'src/shared/copy/notifications' import {rateLimitReached, resultTooLarge} from 'src/shared/copy/notifications'
import {RATE_LIMIT_ERROR_STATUS} from 'src/cloud/constants/index' import {RATE_LIMIT_ERROR_STATUS} from 'src/cloud/constants/index'
// Utils // Utils
@ -113,16 +113,22 @@ export const executeQueries = () => async (dispatch, getState: GetState) => {
pendingResults = queries.map(({text}) => { pendingResults = queries.map(({text}) => {
const windowVars = getWindowVars(text, variableAssignments) const windowVars = getWindowVars(text, variableAssignments)
const extern = buildVarsOption([...variableAssignments, ...windowVars]) const extern = buildVarsOption([...variableAssignments, ...windowVars])
return runQuery(orgID, text, extern) return runQuery(orgID, text, extern)
}) })
const files = await Promise.all( const results = await Promise.all(pendingResults.map(r => r.promise))
pendingResults.map(r => r.promise.then(({csv}) => csv))
)
const duration = Date.now() - startTime const duration = Date.now() - startTime
files.forEach(checkQueryResult) for (const result of results) {
checkQueryResult(result.csv)
if (result.didTruncate) {
dispatch(notify(resultTooLarge(result.bytesRead)))
}
}
const files = results.map(r => r.csv)
dispatch(setQueryResults(RemoteDataState.Done, files, duration)) dispatch(setQueryResults(RemoteDataState.Done, files, duration))
} catch (e) { } catch (e) {