Skip to content

Commit

Permalink
[Reporting] remove async execution from csv_from_savedobject (elastic…
Browse files Browse the repository at this point in the history
…#71031)

* [Reporting] remove async execution from csv_from_savedobject

This simplifies the csv_from_savedobject logic by removing the async
hook. This was added as premature optimization in the initial PR that
added the Download CSV button to the dashboards.

* copy out export type ts changes

* remove routes

* fix i18n
  • Loading branch information
tsullivan committed Jul 9, 2020
1 parent aca9581 commit 521be01
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 335 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export { runTaskFnFactory } from './server/execute_job';

export const getExportType = (): ExportTypeDefinition<
JobParamsPanelCsv,
ImmediateCreateJobFn<JobParamsPanelCsv>,
ImmediateCreateJobFn,
JobParamsPanelCsv,
ImmediateExecuteFn<JobParamsPanelCsv>
ImmediateExecuteFn
> => ({
...metadata,
jobType: CSV_FROM_SAVEDOBJECT_JOB_TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import {
} from '../../types';
import { createJobSearch } from './create_job_search';

export type ImmediateCreateJobFn<JobParamsType> = (
jobParams: JobParamsType,
export type ImmediateCreateJobFn = (
jobParams: JobParamsPanelCsv,
headers: KibanaRequest['headers'],
context: RequestHandlerContext,
req: KibanaRequest
) => Promise<{
type: string | null;
title: string;
jobParams: JobParamsType;
jobParams: JobParamsPanelCsv;
}>;

interface VisData {
Expand All @@ -37,9 +37,10 @@ interface VisData {
panel: SearchPanel;
}

export const scheduleTaskFnFactory: ScheduleTaskFnFactory<ImmediateCreateJobFn<
JobParamsPanelCsv
>> = function createJobFactoryFn(reporting, parentLogger) {
export const scheduleTaskFnFactory: ScheduleTaskFnFactory<ImmediateCreateJobFn> = function createJobFactoryFn(
reporting,
parentLogger
) {
const config = reporting.getConfig();
const crypto = cryptoFactory(config.get('encryptionKey'));
const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'create-job']);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,43 @@
import { i18n } from '@kbn/i18n';
import { KibanaRequest, RequestHandlerContext } from 'src/core/server';
import { CONTENT_TYPE_CSV, CSV_FROM_SAVEDOBJECT_JOB_TYPE } from '../../../../common/constants';
import { cryptoFactory } from '../../../lib';
import { RunTaskFnFactory, ScheduledTaskParams, TaskRunResult } from '../../../types';
import { CsvResultFromSearch } from '../../csv/types';
import { FakeRequest, JobParamsPanelCsv, SearchPanel } from '../types';
import { JobParamsPanelCsv, SearchPanel } from '../types';
import { createGenerateCsv } from './lib';

/*
* The run function receives the full request which provides the un-encrypted
* headers, so encrypted headers are not part of these kind of job params
*/
type ImmediateJobParams = Omit<ScheduledTaskParams<JobParamsPanelCsv>, 'headers'>;

/*
* ImmediateExecuteFn receives the job doc payload because the payload was
* generated in the ScheduleFn
*/
export type ImmediateExecuteFn<JobParamsType> = (
export type ImmediateExecuteFn = (
jobId: null,
job: ScheduledTaskParams<JobParamsType>,
job: ImmediateJobParams,
context: RequestHandlerContext,
req: KibanaRequest
) => Promise<TaskRunResult>;

export const runTaskFnFactory: RunTaskFnFactory<ImmediateExecuteFn<
JobParamsPanelCsv
>> = function executeJobFactoryFn(reporting, parentLogger) {
const config = reporting.getConfig();
const crypto = cryptoFactory(config.get('encryptionKey'));
export const runTaskFnFactory: RunTaskFnFactory<ImmediateExecuteFn> = function executeJobFactoryFn(
reporting,
parentLogger
) {
const logger = parentLogger.clone([CSV_FROM_SAVEDOBJECT_JOB_TYPE, 'execute-job']);
const generateCsv = createGenerateCsv(reporting, parentLogger);

return async function runTask(jobId: string | null, job, context, req) {
return async function runTask(jobId: string | null, job, context, request) {
// There will not be a jobID for "immediate" generation.
// jobID is only for "queued" jobs
// Use the jobID as a logging tag or "immediate"
const jobLogger = logger.clone([jobId === null ? 'immediate' : jobId]);

const { jobParams } = job;
const { isImmediate, panel, visType } = jobParams as JobParamsPanelCsv & { panel: SearchPanel };
const { panel, visType } = jobParams as JobParamsPanelCsv & { panel: SearchPanel };

if (!panel) {
i18n.translate(
Expand All @@ -50,54 +54,13 @@ export const runTaskFnFactory: RunTaskFnFactory<ImmediateExecuteFn<

jobLogger.debug(`Execute job generating [${visType}] csv`);

let requestObject: KibanaRequest | FakeRequest;

if (isImmediate && req) {
jobLogger.info(`Executing job from Immediate API using request context`);
requestObject = req;
} else {
jobLogger.info(`Executing job async using encrypted headers`);
let decryptedHeaders: Record<string, unknown>;
const serializedEncryptedHeaders = job.headers;
try {
if (typeof serializedEncryptedHeaders !== 'string') {
throw new Error(
i18n.translate(
'xpack.reporting.exportTypes.csv_from_savedobject.executeJob.missingJobHeadersErrorMessage',
{
defaultMessage: 'Job headers are missing',
}
)
);
}
decryptedHeaders = (await crypto.decrypt(serializedEncryptedHeaders)) as Record<
string,
unknown
>;
} catch (err) {
jobLogger.error(err);
throw new Error(
i18n.translate(
'xpack.reporting.exportTypes.csv_from_savedobject.executeJob.failedToDecryptReportJobDataErrorMessage',
{
defaultMessage:
'Failed to decrypt report job data. Please ensure that {encryptionKey} is set and re-generate this report. {err}',
values: { encryptionKey: 'xpack.reporting.encryptionKey', err },
}
)
);
}

requestObject = { headers: decryptedHeaders };
}

let content: string;
let maxSizeReached = false;
let size = 0;
try {
const generateResults: CsvResultFromSearch = await generateCsv(
context,
requestObject,
request,
visType as string,
panel,
jobParams
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ export interface JobParamsPanelCsv {
visType?: string;
}

export interface ScheduledTaskParamsPanelCsv extends ScheduledTaskParams<JobParamsPanelCsv> {
jobParams: JobParamsPanelCsv;
}

export interface SavedObjectServiceError {
statusCode: number;
error?: string;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { API_BASE_GENERATE_V1 } from '../../common/constants';
import { scheduleTaskFnFactory } from '../export_types/csv_from_savedobject/server/create_job';
import { runTaskFnFactory } from '../export_types/csv_from_savedobject/server/execute_job';
import { getJobParamsFromRequest } from '../export_types/csv_from_savedobject/server/lib/get_job_params_from_request';
import { ScheduledTaskParamsPanelCsv } from '../export_types/csv_from_savedobject/types';
import { LevelLogger as Logger } from '../lib';
import { TaskRunResult } from '../types';
import { authorizedUserPreRoutingFactory } from './lib/authorized_user_pre_routing';
Expand Down Expand Up @@ -64,12 +63,8 @@ export function registerGenerateCsvFromSavedObjectImmediate(
const runTaskFn = runTaskFnFactory(reporting, logger);

try {
const jobDocPayload: ScheduledTaskParamsPanelCsv = await scheduleTaskFn(
jobParams,
req.headers,
context,
req
);
// FIXME: no scheduleTaskFn for immediate download
const jobDocPayload = await scheduleTaskFn(jobParams, req.headers, context, req);
const {
content_type: jobOutputContentType,
content: jobOutputContent,
Expand All @@ -91,11 +86,12 @@ export function registerGenerateCsvFromSavedObjectImmediate(
return res.ok({
body: jobOutputContent || '',
headers: {
'content-type': jobOutputContentType,
'content-type': jobOutputContentType ? jobOutputContentType : [],
'accept-ranges': 'none',
},
});
} catch (err) {
logger.error(err);
return handleError(res, err);
}
})
Expand Down
Loading

0 comments on commit 521be01

Please sign in to comment.