feat(ui): display notification when Flux response is truncated
parent
e62fbe6242
commit
8a5dcd5707
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue