Skip to content

Commit

Permalink
Upgrade API files to typescript (#25098)
Browse files Browse the repository at this point in the history
* Upgrade some of the migrations to ts.

* Update types.

* Update get type for useConfirmMarkTask.

* Migrate useMarkFailedRun

* migrate useMarkFailedTask, useMarkSuccessRun, useMarkSuccessTask

* Migrate more

* Use API types when possible

* Migrate more

* Add URLSearchParamsWrapper

* Migrate more
  • Loading branch information
pierrejeambrun authored Aug 29, 2022
1 parent 018f1d5 commit 9c592cb
Show file tree
Hide file tree
Showing 30 changed files with 223 additions and 161 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,31 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../utils/useErrorToast';

const csrfToken = getMetaValue('csrf_token');
const clearRunUrl = getMetaValue('dagrun_clear_url');

export default function useClearRun(dagId, runId) {
export default function useClearRun(dagId: string, runId: string) {
const queryClient = useQueryClient();
const errorToast = useErrorToast();
const { startRefresh } = useAutoRefresh();
return useMutation(
['dagRunClear', dagId, runId],
({ confirmed = false }) => {
const params = new URLSearchParams({
({ confirmed = false }: { confirmed: boolean }) => {
const params = new URLSearchParamsWrapper({
csrf_token: csrfToken,
confirmed,
dag_id: dagId,
dag_run_id: runId,
}).toString();

return axios.post(clearRunUrl, params, {
return axios.post<AxiosResponse, string>(clearRunUrl, params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
Expand All @@ -52,7 +53,7 @@ export default function useClearRun(dagId, runId) {
queryClient.invalidateQueries('gridData');
startRefresh();
},
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation, useQueryClient } from 'react-query';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import { useAutoRefresh } from '../context/autorefresh';
import useErrorToast from '../utils/useErrorToast';
Expand All @@ -28,7 +29,10 @@ const clearUrl = getMetaValue('clear_url');

export default function useClearTask({
dagId, runId, taskId, executionDate,
}) {
}: { dagId: string,
runId: string,
taskId: string,
executionDate: string }) {
const queryClient = useQueryClient();
const errorToast = useErrorToast();
const { startRefresh } = useAutoRefresh();
Expand All @@ -37,8 +41,15 @@ export default function useClearTask({
['clearTask', dagId, runId, taskId],
({
past, future, upstream, downstream, recursive, failed, confirmed, mapIndexes = [],
}) => {
const params = new URLSearchParams({
}: { past: boolean,
future: boolean,
upstream: boolean,
downstream: boolean,
recursive: boolean,
failed: boolean,
confirmed: boolean,
mapIndexes: number[] }) => {
const params = new URLSearchParamsWrapper({
csrf_token: csrfToken,
dag_id: dagId,
dag_run_id: runId,
Expand All @@ -53,11 +64,11 @@ export default function useClearTask({
only_failed: failed,
});

mapIndexes.forEach((mi) => {
params.append('map_index', mi);
mapIndexes.forEach((mi: number) => {
params.append('map_index', mi.toString());
});

return axios.post(clearUrl, params.toString(), {
return axios.post<AxiosResponse, string>(clearUrl, params.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
Expand All @@ -69,7 +80,7 @@ export default function useClearTask({
queryClient.invalidateQueries(['mappedInstances', dagId, runId, taskId]);
startRefresh();
},
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,31 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useMutation } from 'react-query';
import type { TaskState } from 'src/types';
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';
import { getMetaValue } from '../utils';
import useErrorToast from '../utils/useErrorToast';

const confirmUrl = getMetaValue('confirm_url');

export default function useConfirmMarkTask({
dagId, runId, taskId, state,
}) {
}: { dagId: string, runId: string, taskId: string, state: TaskState }) {
const errorToast = useErrorToast();
return useMutation(
['confirmStateChange', dagId, runId, taskId, state],
({
past, future, upstream, downstream, mapIndexes = [],
}: {
past: boolean,
future: boolean,
upstream: boolean,
downstream: boolean,
mapIndexes: number[],
}) => {
const params = new URLSearchParams({
const params = new URLSearchParamsWrapper({
dag_id: dagId,
dag_run_id: runId,
task_id: taskId,
Expand All @@ -44,14 +52,13 @@ export default function useConfirmMarkTask({
state,
});

mapIndexes.forEach((mi) => {
params.append('map_index', mi);
mapIndexes.forEach((mi: number) => {
params.append('map_index', mi.toString());
});

return axios.get(confirmUrl, { params });
return axios.get<AxiosResponse, string[]>(confirmUrl, { params });
},
{
onError: (error) => errorToast({ error }),
onError: (error: Error) => errorToast({ error }),
},
);
}
10 changes: 3 additions & 7 deletions airflow/www/static/js/api/useDataset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,11 @@ import { useQuery } from 'react-query';
import { getMetaValue } from 'src/utils';
import type { API } from 'src/types';

interface Props {
datasetUri: string;
}

export default function useDataset({ datasetUri }: Props) {
export default function useDataset({ uri }: API.GetDatasetVariables) {
return useQuery(
['dataset', datasetUri],
['dataset', uri],
() => {
const datasetUrl = `${getMetaValue('datasets_api') || '/api/v1/datasets'}/${encodeURIComponent(datasetUri)}`;
const datasetUrl = `${getMetaValue('datasets_api') || '/api/v1/datasets'}/${encodeURIComponent(uri)}`;
return axios.get<AxiosResponse, API.Dataset>(datasetUrl);
},
);
Expand Down
37 changes: 11 additions & 26 deletions airflow/www/static/js/api/useDatasetEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,43 +22,28 @@ import { useQuery } from 'react-query';

import { getMetaValue } from 'src/utils';
import type { API } from 'src/types';

interface DatasetEventsData {
datasetEvents: API.DatasetEvent[];
totalEntries: number;
}

interface Props {
datasetId?: number;
dagId?: string;
taskId?: string;
runId?: string;
mapIndex?: number;
limit?: number;
offset?: number;
order?: string;
}
import URLSearchParamsWrapper from 'src/utils/URLSearchParamWrapper';

export default function useDatasetEvents({
datasetId, dagId, runId, taskId, mapIndex, limit, offset, order,
}: Props) {
datasetId, sourceDagId, sourceRunId, sourceTaskId, sourceMapIndex, limit, offset, orderBy,
}: API.GetDatasetEventsVariables) {
const query = useQuery(
['datasets-events', datasetId, dagId, runId, taskId, mapIndex, limit, offset, order],
['datasets-events', datasetId, sourceDagId, sourceRunId, sourceTaskId, sourceMapIndex, limit, offset, orderBy],
() => {
const datasetsUrl = getMetaValue('dataset_events_api') || '/api/v1/datasets/events';

const params = new URLSearchParams();
const params = new URLSearchParamsWrapper();

if (limit) params.set('limit', limit.toString());
if (offset) params.set('offset', offset.toString());
if (order) params.set('order_by', order);
if (orderBy) params.set('order_by', orderBy);
if (datasetId) params.set('dataset_id', datasetId.toString());
if (dagId) params.set('source_dag_id', dagId);
if (runId) params.set('source_run_id', runId);
if (taskId) params.set('source_task_id', taskId);
if (mapIndex) params.set('source_map_index', mapIndex.toString());
if (sourceDagId) params.set('source_dag_id', sourceDagId);
if (sourceRunId) params.set('source_run_id', sourceRunId);
if (sourceTaskId) params.set('source_task_id', sourceTaskId);
if (sourceMapIndex) params.set('source_map_index', sourceMapIndex.toString());

return axios.get<AxiosResponse, DatasetEventsData>(datasetsUrl, {
return axios.get<AxiosResponse, API.DatasetEventCollection>(datasetsUrl, {
params,
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,21 @@
* under the License.
*/

import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { useQuery } from 'react-query';
import { getMetaValue } from '../utils';

const extraLinksUrl = getMetaValue('extra_links_url');

interface LinkData {
url: string | null;
error: string | null;
}

export default function useExtraLinks({
dagId, taskId, executionDate, extraLinks,
}: {
dagId: string, taskId: string, executionDate: string, extraLinks: string[],
}) {
return useQuery(
['extraLinks', dagId, taskId, executionDate],
Expand All @@ -36,7 +43,7 @@ export default function useExtraLinks({
}&execution_date=${encodeURIComponent(executionDate)
}&link_name=${encodeURIComponent(link)}`;
try {
const datum = await axios.get(url);
const datum = await axios.get<AxiosResponse, LinkData>(url);
return {
name: link,
url: datum.url,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,53 @@

/* global describe, test, expect */

import type { DagRun } from 'src/types';
import { areActiveRuns } from './useGridData';

const commonDagRunParams = {
runId: 'runId',
executionDate: '2022-01-01T10:00+00:00',
dataIntervalStart: '2022-01-01T05:00+00:00',
dataIntervalEnd: '2022-01-01T10:00+00:00',
startDate: null,
endDate: null,
lastSchedulingDecision: null,
};

describe('Test areActiveRuns()', () => {
test('Correctly detects active runs', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'queued' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'queued', ...commonDagRunParams },
];
expect(areActiveRuns(runs)).toBe(true);
});

test('Returns false when all runs are resolved', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'manual', state: 'failed' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
});

test('Returns false when filtering runs runtype ["backfill"] and state ["failed"]', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'backfill', state: 'failed' },
test('Returns false when filtering runs runtype ["backfill"]', () => {
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'backfill', state: 'failed', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
});

test('Returns false when filtering runs runtype ["backfill"] and state ["queued"]', () => {
const runs = [
{ runType: 'scheduled', state: 'success' },
{ runType: 'manual', state: 'failed' },
{ runType: 'backfill', state: 'queued' },
const runs: DagRun[] = [
{ runType: 'scheduled', state: 'success', ...commonDagRunParams },
{ runType: 'manual', state: 'failed', ...commonDagRunParams },
{ runType: 'backfill', state: 'queued', ...commonDagRunParams },
];
const result = areActiveRuns(runs);
expect(result).toBe(false);
Expand Down Expand Up @@ -87,7 +98,7 @@ describe('Test areActiveRuns()', () => {
},
].forEach(({ state, runType, expectedResult }) => {
test(`Returns ${expectedResult} when filtering runs with runtype ["${runType}"] and state ["${state}"]`, () => {
const runs = [{ runType, state }];
const runs: DagRun[] = [{ runType, state, ...commonDagRunParams } as DagRun];
const result = areActiveRuns(runs);
expect(result).toBe(expectedResult);
});
Expand Down
28 changes: 7 additions & 21 deletions airflow/www/static/js/api/useMappedInstances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,33 +22,19 @@ import { useQuery } from 'react-query';

import { getMetaValue } from 'src/utils';
import { useAutoRefresh } from 'src/context/autorefresh';
import type { API, DagRun } from 'src/types';
import type { API } from 'src/types';

const mappedInstancesUrl = getMetaValue('mapped_instances_api');

interface MappedInstanceData {
taskInstances: API.TaskInstance[];
totalEntries: number;
}

interface Props {
dagId: string;
runId: DagRun['runId'];
taskId: string;
limit?: number;
offset?: number;
order?: string;
}

export default function useMappedInstances({
dagId, runId, taskId, limit, offset, order,
}: Props) {
const url = mappedInstancesUrl.replace('_DAG_RUN_ID_', runId).replace('_TASK_ID_', taskId);
const orderParam = order && order !== 'map_index' ? { order_by: order } : {};
dagId, dagRunId, taskId, limit, offset, orderBy,
}: API.GetMappedTaskInstancesVariables) {
const url = mappedInstancesUrl.replace('_DAG_RUN_ID_', dagRunId).replace('_TASK_ID_', taskId);
const orderParam = orderBy && orderBy !== 'map_index' ? { order_by: orderBy } : {};
const { isRefreshOn } = useAutoRefresh();
return useQuery(
['mappedInstances', dagId, runId, taskId, offset, order],
() => axios.get<AxiosResponse, MappedInstanceData>(url, {
['mappedInstances', dagId, dagRunId, taskId, offset, orderBy],
() => axios.get<AxiosResponse, API.TaskInstanceCollection>(url, {
params: { offset, limit, ...orderParam },
}),
{
Expand Down
Loading

0 comments on commit 9c592cb

Please sign in to comment.