Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Reporting] remove async execution from csv_from_savedobject #71031

Merged
merged 5 commits into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
Copy link
Member Author

@tsullivan tsullivan Jul 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is what creates the complexity with getting Reporting to work with Task Manager. This CSV export handler uses the same methods other export types use for queuing, but that bind needs to be separated since this handler is responsible for "immediate" download of CSV without queuing.

By simplifying some TypeScript, this PR does enough to separate the bind to allow moving ahead with Task Manager work in Reporting.

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