Merge branch 'fix/api-timeouts' into 'release'

Api timeout changes

See merge request theappsmith/internal-tools-client!554
This commit is contained in:
Hetu Nandu 2020-05-07 08:07:29 +00:00
commit 42f99e766b
6 changed files with 50 additions and 16 deletions

View File

@ -1,6 +1,9 @@
import API, { HttpMethod } from "./Api"; import API, { HttpMethod } from "./Api";
import { ApiResponse, GenericApiResponse, ResponseMeta } from "./ApiResponses"; import { ApiResponse, GenericApiResponse, ResponseMeta } from "./ApiResponses";
import { APIRequest, EXECUTE_ACTION_TIMEOUT_MS } from "constants/ApiConstants"; import {
APIRequest,
DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
} from "constants/ApiConstants";
import { AxiosPromise } from "axios"; import { AxiosPromise } from "axios";
import { Datasource } from "./DatasourcesApi"; import { Datasource } from "./DatasourcesApi";
import { PaginationType } from "pages/Editor/APIEditor/Pagination"; import { PaginationType } from "pages/Editor/APIEditor/Pagination";
@ -50,6 +53,7 @@ export interface APIConfigRequest {
queryParameters: Property[]; queryParameters: Property[];
paginationType: PaginationType; paginationType: PaginationType;
bodyFormData: BodyFormData[]; bodyFormData: BodyFormData[];
timeoutInMillisecond: number;
} }
export interface QueryConfig { export interface QueryConfig {
@ -197,9 +201,10 @@ class ActionAPI extends API {
static executeAction( static executeAction(
executeAction: ExecuteActionRequest, executeAction: ExecuteActionRequest,
timeout?: number,
): AxiosPromise<ActionApiResponse> { ): AxiosPromise<ActionApiResponse> {
return API.post(ActionAPI.url + "/execute", executeAction, undefined, { return API.post(ActionAPI.url + "/execute", executeAction, undefined, {
timeout: EXECUTE_ACTION_TIMEOUT_MS, timeout: timeout || DEFAULT_EXECUTE_ACTION_TIMEOUT_MS,
}); });
} }

View File

@ -1,7 +1,7 @@
import API from "./Api"; import API from "./Api";
import { GenericApiResponse } from "./ApiResponses"; import { GenericApiResponse } from "./ApiResponses";
import { AxiosPromise } from "axios"; import { AxiosPromise } from "axios";
import { EXECUTE_ACTION_TIMEOUT_MS } from "constants/ApiConstants"; import { DEFAULT_TEST_DATA_SOURCE_TIMEOUT_MS } from "constants/ApiConstants";
interface DatasourceAuthentication { interface DatasourceAuthentication {
authType?: string; authType?: string;
@ -50,7 +50,7 @@ class DatasourcesApi extends API {
static testDatasource(datasourceConfig: Partial<Datasource>): Promise<{}> { static testDatasource(datasourceConfig: Partial<Datasource>): Promise<{}> {
return API.post(`${DatasourcesApi.url}/test`, datasourceConfig, undefined, { return API.post(`${DatasourcesApi.url}/test`, datasourceConfig, undefined, {
timeout: EXECUTE_ACTION_TIMEOUT_MS, timeout: DEFAULT_TEST_DATA_SOURCE_TIMEOUT_MS,
}); });
} }

View File

@ -53,6 +53,7 @@ export interface PageAction {
pluginType: ActionType; pluginType: ActionType;
name: string; name: string;
jsonPathKeys: string[]; jsonPathKeys: string[];
timeoutInMillisecond: number;
} }
export interface ExecuteErrorPayload { export interface ExecuteErrorPayload {

View File

@ -3,7 +3,8 @@ export type ContentType =
| "application/x-www-form-urlencoded"; | "application/x-www-form-urlencoded";
export const REQUEST_TIMEOUT_MS = 10000; export const REQUEST_TIMEOUT_MS = 10000;
export const EXECUTE_ACTION_TIMEOUT_MS = 15000; export const DEFAULT_EXECUTE_ACTION_TIMEOUT_MS = 15000;
export const DEFAULT_TEST_DATA_SOURCE_TIMEOUT_MS = 30000;
export const API_REQUEST_HEADERS: APIHeaders = { export const API_REQUEST_HEADERS: APIHeaders = {
"Content-Type": "application/json", "Content-Type": "application/json",

View File

@ -83,6 +83,22 @@ export const getAction = (
return action ? action.config : undefined; return action ? action.config : undefined;
}; };
export const getActionTimeout = (
state: AppState,
actionId: string,
): number | undefined => {
const action = _.find(state.entities.actions, a => a.config.id === actionId);
if (action) {
const timeout = action.config.actionConfiguration.timeoutInMillisecond;
if (timeout) {
// Extra timeout padding to account for network calls
return timeout + 5000;
}
return undefined;
}
return undefined;
};
const createActionSuccessResponse = ( const createActionSuccessResponse = (
response: ActionApiResponse, response: ActionApiResponse,
): ActionResponse => ({ ): ActionResponse => ({
@ -185,8 +201,10 @@ export function* executeActionSaga(
params, params,
paginationField: pagination, paginationField: pagination,
}; };
const timeout = yield select(getActionTimeout, actionId);
const response: ActionApiResponse = yield ActionAPI.executeAction( const response: ActionApiResponse = yield ActionAPI.executeAction(
executeActionRequest, executeActionRequest,
timeout,
); );
if (isErrorResponse(response)) { if (isErrorResponse(response)) {
const payload = createActionErrorResponse(response); const payload = createActionErrorResponse(response);
@ -552,11 +570,15 @@ export function* runApiActionSaga(
const { paginationField } = reduxAction.payload; const { paginationField } = reduxAction.payload;
const params = yield call(getActionParams, jsonPathKeys); const params = yield call(getActionParams, jsonPathKeys);
const response: ActionApiResponse = yield ActionAPI.executeAction({ const timeout = yield select(getActionTimeout, values.id);
const response: ActionApiResponse = yield ActionAPI.executeAction(
{
action, action,
params, params,
paginationField, paginationField,
}); },
timeout,
);
let payload = createActionSuccessResponse(response); let payload = createActionSuccessResponse(response);
if (response.responseMeta && response.responseMeta.error) { if (response.responseMeta && response.responseMeta.error) {
payload = createActionErrorResponse(response); payload = createActionErrorResponse(response);
@ -597,6 +619,7 @@ function* executePageLoadAction(pageAction: PageAction) {
}; };
const response: ActionApiResponse = yield ActionAPI.executeAction( const response: ActionApiResponse = yield ActionAPI.executeAction(
executeActionRequest, executeActionRequest,
pageAction.timeoutInMillisecond,
); );
if (isErrorResponse(response)) { if (isErrorResponse(response)) {

View File

@ -27,7 +27,7 @@ import {
getCurrentPageId, getCurrentPageId,
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { initialize } from "redux-form"; import { initialize } from "redux-form";
import { getAction, getActionParams } from "./ActionSagas"; import { getAction, getActionParams, getActionTimeout } from "./ActionSagas";
import { AppState } from "reducers"; import { AppState } from "reducers";
import ActionAPI, { import ActionAPI, {
RestAction, RestAction,
@ -214,11 +214,15 @@ export function* executeQuerySaga(
const { paginationField } = actionPayload.payload; const { paginationField } = actionPayload.payload;
const params = yield call(getActionParams, jsonPathKeys); const params = yield call(getActionParams, jsonPathKeys);
const response: ActionApiResponse = yield ActionAPI.executeAction({ const timeout = yield select(getActionTimeout, values.id);
const response: ActionApiResponse = yield ActionAPI.executeAction(
{
action, action,
params, params,
paginationField, paginationField,
}); },
timeout,
);
if (response.responseMeta && response.responseMeta.error) { if (response.responseMeta && response.responseMeta.error) {
throw response.responseMeta.error; throw response.responseMeta.error;