From 8a5dcd570761c624c735eb2fdffa80585dd2287e Mon Sep 17 00:00:00 2001 From: Christopher Henn Date: Wed, 31 Jul 2019 14:33:00 -0700 Subject: [PATCH] feat(ui): display notification when Flux response is truncated --- ui/src/shared/components/TimeSeries.tsx | 19 +++++++++++------ ui/src/shared/constants/index.ts | 4 ++-- ui/src/shared/copy/notifications.ts | 28 ++++++++++++++++++++----- ui/src/timeMachine/actions/queries.ts | 18 ++++++++++------ 4 files changed, 50 insertions(+), 19 deletions(-) diff --git a/ui/src/shared/components/TimeSeries.tsx b/ui/src/shared/components/TimeSeries.tsx index 3f65749f8b..f258f3c743 100644 --- a/ui/src/shared/components/TimeSeries.tsx +++ b/ui/src/shared/components/TimeSeries.tsx @@ -15,7 +15,7 @@ import {buildVarsOption} from 'src/variables/utils/buildVarsOption' // Constants 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' // Actions @@ -139,17 +139,24 @@ class TimeSeries extends Component { this.pendingResults = queries.map(({text}) => { const windowVars = getWindowVars(text, variables) const extern = buildVarsOption([...variables, ...windowVars]) + return runQuery(orgID, text, extern) }) // Wait for new queries to complete - const files = await Promise.all( - this.pendingResults.map(r => r.promise.then(({csv}) => csv)) - ) + const results = await Promise.all(this.pendingResults.map(r => r.promise)) 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({ giraffeResult, diff --git a/ui/src/shared/constants/index.ts b/ui/src/shared/constants/index.ts index b96e8e5885..aeb983bcf8 100644 --- a/ui/src/shared/constants/index.ts +++ b/ui/src/shared/constants/index.ts @@ -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 FLUX_RESPONSE_BYTES_LIMIT = CLOUD - ? 10 * 1024 * 1024 - : 100 * 1024 * 1024 + ? 10 * 1024 * 1024 // 10 MiB + : 100 * 1024 * 1024 // 100 MiB export const VIS_SIG_DIGITS = 4 diff --git a/ui/src/shared/copy/notifications.ts b/ui/src/shared/copy/notifications.ts index 2700c3aaf0..f3386d153c 100644 --- a/ui/src/shared/copy/notifications.ts +++ b/ui/src/shared/copy/notifications.ts @@ -1,16 +1,25 @@ -// All copy for notifications should be stored here for easy editing -// and ensuring stylistic consistency +// Libraries +import {binaryPrefixFormatter} from '@influxdata/giraffe' + +// Types import {Notification} from 'src/types' 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< Notification, Exclude > -import {FIVE_SECONDS, TEN_SECONDS, INFINITE} from 'src/shared/constants/index' -import {QUICKSTART_SCRAPER_TARGET_URL} from 'src/dataLoaders/constants/pluginConfigs' - const defaultErrorNotification: NotificationExcludingMessage = { style: NotificationStyle.Error, icon: 'alert-triangle', @@ -58,6 +67,15 @@ export const sessionTimedOut = (): Notification => ({ 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 export const SetupSuccess: Notification = { ...defaultSuccessNotification, diff --git a/ui/src/timeMachine/actions/queries.ts b/ui/src/timeMachine/actions/queries.ts index 3fca55e8d1..d97a15a87c 100644 --- a/ui/src/timeMachine/actions/queries.ts +++ b/ui/src/timeMachine/actions/queries.ts @@ -8,7 +8,7 @@ import {refreshVariableValues, selectValue} from 'src/variables/actions' import {notify} from 'src/shared/actions/notifications' // 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' // Utils @@ -113,16 +113,22 @@ export const executeQueries = () => async (dispatch, getState: GetState) => { pendingResults = queries.map(({text}) => { const windowVars = getWindowVars(text, variableAssignments) const extern = buildVarsOption([...variableAssignments, ...windowVars]) + return runQuery(orgID, text, extern) }) - const files = await Promise.all( - pendingResults.map(r => r.promise.then(({csv}) => csv)) - ) - + const results = await Promise.all(pendingResults.map(r => r.promise)) 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)) } catch (e) {