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] Clean up types for internal APIs needed for UI #105508

Merged
merged 13 commits into from
Jul 15, 2021
Merged
120 changes: 61 additions & 59 deletions x-pack/plugins/reporting/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,31 +55,39 @@ export interface TaskRunResult {
}

export interface ReportSource {
jobtype: string;
kibana_name: string;
kibana_id: string;
created_by: string | false;
/*
* Required fields: populated in enqueue_job when the request comes in to
* generate the report
*/
jobtype: string; // refers to `ExportTypeDefinition.jobType`
created_by: string | false; // username or `false` if security is disabled. Used for ensuring users can only access the reports they've created.
payload: {
headers: string; // encrypted headers
browserTimezone?: string; // may use timezone from advanced settings
objectType: string;
title: string;
layout?: LayoutParams;
isDeprecated?: boolean;
};
meta: { objectType: string; layout?: string };
browser_type: string;
migration_version: string;
max_attempts: number;
timeout: number;

isDeprecated?: boolean; // set to true when the export type is being phased out
} & BaseParams;
meta: { objectType: string; layout?: string }; // for telemetry
migration_version: string; // for reminding the user to update their POST URL
attempts: number; // initially populated as 0
created_at: string; // timestamp in UTC
status: JobStatus;
attempts: number;

/*
* `output` is only populated if the report job is completed or failed.
*/
output: TaskRunResult | null;
tsullivan marked this conversation as resolved.
Show resolved Hide resolved
started_at?: string;
completed_at?: string;
created_at: string;
process_expiration?: string | null; // must be set to null to clear the expiration

/*
* Optional fields: populated when the job is claimed to execute, and after
* execution has finished
*/
kibana_name?: string; // for troubleshooting
kibana_id?: string; // for troubleshooting
browser_type?: string; // no longer used since chromium is the only option (used to allow phantomjs)
timeout?: number; // for troubleshooting: the actual comparison uses the config setting xpack.reporting.queue.timeout
max_attempts?: number; // for troubleshooting: the actual comparison uses the config setting xpack.reporting.capture.maxAttempts
started_at?: string; // timestamp in UTC
completed_at?: string; // timestamp in UTC
process_expiration?: string | null; // timestamp in UTC - is overwritten with `null` when the job needs a retry
}

/*
Expand All @@ -97,48 +105,41 @@ export interface BaseParams {
}

export type JobId = string;

/*
* JobStatus:
* - Begins as 'pending'
* - Changes to 'processing` when the job is claimed
* - Then 'completed' | 'failed' when execution is done
* If the job needs a retry, it reverts back to 'pending'.
*/
export type JobStatus =
| 'completed'
| 'completed_with_warnings'
| 'pending'
| 'processing'
| 'failed';
| 'completed' // Report was successful
| 'completed_with_warnings' // The download available for troubleshooting - it **should** show a meaningful error
| 'pending' // Report job is waiting to be claimed
| 'processing' // Report job has been claimed and is executing
| 'failed'; // Report was not successful, and all retries are done. Nothing to download.

export interface JobContent {
content: string;
}

export interface ReportApiJSON {
/*
* Info API response: to avoid unnecessary large payloads on a network, the
* report query results do not include `payload.headers` or `output.content`,
* which can be long strings of meaningless text
*/
interface ReportSimple extends Omit<ReportSource, 'payload' | 'output'> {
payload: Omit<ReportSource['payload'], 'headers'>;
output?: Omit<TaskRunResult, 'content'>; // is undefined for report jobs that are not completed
}

/*
* The response format for all of the report job APIs
*/
export interface ReportApiJSON extends ReportSimple {
id: string;
index: string;
kibana_name: string;
kibana_id: string;
browser_type: string | undefined;
created_at: string;
jobtype: string;
created_by: string | false;
timeout?: number;
output?: {
content_type: string;
size: number;
warnings?: string[];
};
process_expiration?: string;
completed_at: string | undefined;
payload: {
layout?: LayoutParams;
title: string;
browserTimezone?: string;
isDeprecated?: boolean;
};
meta: {
layout?: string;
objectType: string;
};
max_attempts: number;
started_at: string | undefined;
attempts: number;
status: string;
Copy link
Member Author

Choose a reason for hiding this comment

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

This was all nearly duplicated from ReportSource

}

export interface LicenseCheckResults {
Expand All @@ -147,13 +148,14 @@ export interface LicenseCheckResults {
message: string;
}

/* Notifier Toasts */
export interface JobSummary {
id: JobId;
status: JobStatus;
title: string;
jobtype: string;
maxSizeReached?: boolean;
csvContainsFormulas?: boolean;
jobtype: ReportSource['jobtype'];
title: ReportSource['payload']['title'];
maxSizeReached: TaskRunResult['max_size_reached'];
csvContainsFormulas: TaskRunResult['csv_contains_formulas'];
}

export interface JobSummarySet {
Expand Down
75 changes: 75 additions & 0 deletions x-pack/plugins/reporting/public/lib/job.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { JobId, ReportApiJSON, ReportSource, TaskRunResult } from '../../common/types';

type ReportPayload = ReportSource['payload'];

/*
* This class represents a report job for the UI
* It can be instantiated with ReportApiJSON: the response data format for the report job APIs
*/
export class Job {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are we using a class here? I think we could accomplish the same thing with just an interface and a function that maps one object to another (if needed). Unless we intend to associate behaviours with this in way that is in keeping with how we use classes elsewhere in Reporting.

Copy link
Member Author

@tsullivan tsullivan Jul 14, 2021

Choose a reason for hiding this comment

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

Unless we intend to associate behaviours with this in way that is in keeping with how we use classes elsewhere in Reporting.

Yes, this is the case. In an earlier incarnation of the code, there are methods on this class for achieving consistency about warnings [1], and then further on, showing some info about deprecated export types. That got to be a lot of changes in the UI that just needed to be isolated to a separate PR.

[1] Why is the only warning shown in a table cell about when the max size was reached? Why don't we use the table to show that a CSV could contain formulas, but we do show it in the toast notification? Why doesn't the info side panel show "status" the same way it's shown in the table?

public id: JobId;
public index: string;

public objectType: ReportPayload['objectType'];
public title: ReportPayload['title'];
public isDeprecated: ReportPayload['isDeprecated'];
public browserTimezone?: ReportPayload['browserTimezone'];
public layout: ReportPayload['layout'];

public jobtype: ReportSource['jobtype'];
public created_by: ReportSource['created_by'];
public created_at: ReportSource['created_at'];
public started_at: ReportSource['started_at'];
public completed_at: ReportSource['completed_at'];
public status: ReportSource['status'];
public attempts: ReportSource['attempts'];
public max_attempts: ReportSource['max_attempts'];

public timeout: ReportSource['timeout'];
public kibana_name: ReportSource['kibana_name'];
public kibana_id: ReportSource['kibana_id'];
public browser_type: ReportSource['browser_type'];

public size?: TaskRunResult['size'];
public content_type?: TaskRunResult['content_type'];
public csv_contains_formulas?: TaskRunResult['csv_contains_formulas'];
public max_size_reached?: TaskRunResult['max_size_reached'];
public warnings?: TaskRunResult['warnings'];

constructor(report: ReportApiJSON) {
this.id = report.id;
this.index = report.index;

this.jobtype = report.jobtype;
this.objectType = report.payload.objectType;
this.title = report.payload.title;
this.layout = report.payload.layout;
this.created_by = report.created_by;
this.created_at = report.created_at;
this.started_at = report.started_at;
this.completed_at = report.completed_at;
this.status = report.status;
this.attempts = report.attempts;
this.max_attempts = report.max_attempts;

this.timeout = report.timeout;
this.kibana_name = report.kibana_name;
this.kibana_id = report.kibana_id;
this.browser_type = report.browser_type;
this.browserTimezone = report.payload.browserTimezone;
this.size = report.output?.size;
this.content_type = report.output?.content_type;

this.isDeprecated = report.payload.isDeprecated || false;
this.csv_contains_formulas = report.output?.csv_contains_formulas;
this.max_size_reached = report.output?.max_size_reached;
this.warnings = report.output?.warnings;
}
}
Loading
Loading