Add error handling to Perfherder createAlert (#5407)

Replace create functions use of fetch with getData and update
use in createAlert, Bugfiler and JobModelClassification model;
cleanup graphsContainer
This commit is contained in:
Sarah Clements 2019-10-04 11:05:29 -07:00 коммит произвёл GitHub
Родитель 2f96be8b2a
Коммит 6f5129ab6e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 75 добавлений и 79 удалений

Просмотреть файл

@ -40,7 +40,7 @@ export const getData = async function getData(url, options = {}) {
// TODO: The credentials param can be removed in July once Firefox 62 ships and it is the default.
export const create = function postJson(uri, data) {
return fetch(uri, {
return getData(uri, {
method: 'POST',
headers: generateHeaders(),
body: JSON.stringify(data),

Просмотреть файл

@ -471,22 +471,16 @@ export class BugFilerClass extends React.Component {
comment_tags: 'treeherder',
};
const bugResp = await create(
const { data, failureStatus } = await create(
getApiUrl('/bugzilla/create_bug/'),
payload,
);
// const bugResp = await create('http://httpstat.us/404', payload);
const data = await bugResp.json();
if (bugResp.ok) {
if (!failureStatus) {
successCallback(data);
toggle();
} else {
this.submitFailure(
'Treeherder Bug Filer API',
bugResp.status,
bugResp.statusText,
data,
);
this.submitFailure('Treeherder Bug Filer API', failureStatus, data);
}
} else {
this.submitFailure(

Просмотреть файл

@ -114,7 +114,7 @@ class PinBoard extends React.Component {
});
};
saveClassification = job => {
saveClassification = async job => {
const { recalculateUnclassifiedCounts, notify } = this.props;
const classification = this.createNewClassification();
@ -125,21 +125,19 @@ class PinBoard extends React.Component {
recalculateUnclassifiedCounts();
classification.job_id = job.id;
return classification
.create()
.then(() => {
notify(`Classification saved for ${job.title}`, 'success');
// update the job to show that it's now classified
const jobInstance = findJobInstance(job.id);
const { data, failureStatus } = await classification.create();
if (!failureStatus) {
notify(`Classification saved for ${job.title}`, 'success');
// update the job to show that it's now classified
const jobInstance = findJobInstance(job.id);
if (jobInstance) {
jobInstance.refilter();
}
})
.catch(response => {
const message = `Error saving classification for ${job.platform} ${job.job_type_name}`;
notify(formatModelError(response, message), 'danger');
});
if (jobInstance) {
jobInstance.refilter();
}
} else {
const message = `Error saving classification for ${job.platform} ${job.job_type_name}: ${data}`;
notify(message, 'danger');
}
}
};

Просмотреть файл

@ -12,7 +12,14 @@ import { create } from '../../helpers/http';
import RepositoryModel from '../../models/repository';
import { displayNumber, getStatus } from '../helpers';
const GraphTooltip = ({ dataPoint, testData, user, updateData, projects }) => {
const GraphTooltip = ({
dataPoint,
testData,
user,
updateData,
projects,
updateStateParams,
}) => {
// we either have partial information provided by the selected
// query parameter or the full dataPoint object provided from the
// graph library
@ -79,29 +86,46 @@ const GraphTooltip = ({ dataPoint, testData, user, updateData, projects }) => {
group_state: 'expanded',
});
// TODO refactor create to use getData wrapper
const createAlert = () =>
create(getApiUrl(endpoints.alertSummary), {
const createAlert = async () => {
let data;
let failureStatus;
({ data, failureStatus } = await create(getApiUrl(endpoints.alertSummary), {
repository_id: testDetails.projectId,
framework_id: testDetails.framework_id,
push_id: dataPointDetails.pushId,
prev_push_id: prevPushId,
})
.then(response => response.json())
.then(response => {
const newAlertSummaryId = response.alert_summary_id;
return create(getApiUrl('/performance/alert/'), {
summary_id: newAlertSummaryId,
signature_id: testDetails.signature_id,
}).then(() =>
updateData(
testDetails.signature_id,
testDetails.projectId,
newAlertSummaryId,
flotIndex,
),
);
}));
if (failureStatus) {
return updateStateParams({
errorMessages: [
`Failed to create an alert summary for push ${dataPointDetails.push_id}: ${data}`,
],
});
}
const newAlertSummaryId = data.alert_summary_id;
({ data, failureStatus } = await create(getApiUrl(endpoints.alert), {
summary_id: newAlertSummaryId,
signature_id: testDetails.signature_id,
}));
if (failureStatus) {
updateStateParams({
errorMessages: [
`Failed to create an alert for alert summary ${newAlertSummaryId}: ${data}`,
],
});
}
updateData(
testDetails.signature_id,
testDetails.projectId,
newAlertSummaryId,
flotIndex,
);
};
return (
<div className="body">

Просмотреть файл

@ -289,11 +289,7 @@ class GraphsContainer extends React.Component {
/>
</span>
{dataPoint && showTooltip && (
<GraphTooltip
dataPoint={dataPoint}
testData={testData}
{...this.props}
/>
<GraphTooltip dataPoint={dataPoint} {...this.props} />
)}
<div className="tip" />
</div>
@ -452,7 +448,6 @@ GraphsContainer.propTypes = {
PropTypes.string,
PropTypes.arrayOf(PropTypes.string),
]),
user: PropTypes.shape({}).isRequired,
timeRange: PropTypes.shape({}).isRequired,
};

Просмотреть файл

@ -28,7 +28,6 @@ import ErrorMessages from '../../shared/ErrorMessages';
import ErrorBoundary from '../../shared/ErrorBoundary';
import LoadingSpinner from '../../shared/LoadingSpinner';
import GraphsContainer from './GraphsContainer';
import LegendCard from './LegendCard';
import GraphsViewControls from './GraphsViewControls';
@ -351,7 +350,7 @@ class GraphsView extends React.Component {
visibilityChanged,
} = this.state;
const { projects, frameworks } = this.props;
const { projects, frameworks, user } = this.props;
return (
<ErrorBoundary
errorClasses={errorMessageClass}
@ -399,36 +398,22 @@ class GraphsView extends React.Component {
<GraphsViewControls
timeRange={timeRange}
frameworks={frameworks}
user={user}
projects={projects}
options={options}
getTestData={this.getTestData}
testData={testData}
showModal={showModal}
toggle={() => this.setState({ showModal: !showModal })}
graphs={
testData.length > 0 && (
<GraphsContainer
timeRange={timeRange}
highlightAlerts={highlightAlerts}
highlightedRevisions={highlightedRevisions}
zoom={zoom}
selectedDataPoint={selectedDataPoint}
testData={testData}
updateStateParams={state =>
this.setState(state, this.changeParams)
}
user={this.props.user}
updateData={this.updateData}
projects={projects}
visibilityChanged={visibilityChanged}
/>
)
}
highlightAlerts={highlightAlerts}
highlightedRevisions={highlightedRevisions}
zoom={zoom}
selectedDataPoint={selectedDataPoint}
updateStateParams={state =>
this.setState(state, this.changeParams)
}
highlightAlerts={highlightAlerts}
highlightedRevisions={highlightedRevisions}
visibilityChanged={visibilityChanged}
updateData={this.updateData}
toggle={() => this.setState({ showModal: !showModal })}
updateTimeRange={timeRange =>
this.setState(
{
@ -464,7 +449,6 @@ GraphsView.propTypes = {
PropTypes.arrayOf(PropTypes.string),
]),
}),
user: PropTypes.shape({}).isRequired,
};
GraphsView.defaultProps = {

Просмотреть файл

@ -14,6 +14,7 @@ import { phTimeRanges } from '../constants';
import DropdownMenuItems from '../../shared/DropdownMenuItems';
import TestDataModal from './TestDataModal';
import GraphsContainer from './GraphsContainer';
export default class GraphsViewControls extends React.Component {
changeHighlightedRevision = (index, newValue) => {
@ -28,7 +29,6 @@ export default class GraphsViewControls extends React.Component {
render() {
const {
timeRange,
graphs,
updateStateParams,
highlightAlerts,
highlightedRevisions,
@ -36,6 +36,7 @@ export default class GraphsViewControls extends React.Component {
hasNoData,
toggle,
showModal,
testData,
} = this.props;
return (
@ -75,7 +76,8 @@ export default class GraphsViewControls extends React.Component {
</Row>
) : (
<React.Fragment>
{graphs}
{testData.length > 0 && <GraphsContainer {...this.props} />}
<Row className="justify-content-start pt-2">
{highlightedRevisions.length > 0 &&
highlightedRevisions.map((revision, index) => (
@ -117,7 +119,6 @@ export default class GraphsViewControls extends React.Component {
GraphsViewControls.propTypes = {
updateStateParams: PropTypes.func.isRequired,
graphs: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]).isRequired,
timeRange: PropTypes.shape({}).isRequired,
highlightAlerts: PropTypes.bool.isRequired,
highlightedRevisions: PropTypes.oneOfType([