Skip to content

Commit

Permalink
[Security Solution] fix flaky endpoint ftr tests (#152119)
Browse files Browse the repository at this point in the history
  • Loading branch information
joeypoon authored Feb 28, 2023
1 parent 6be7e3d commit 7449b0a
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,13 @@ describe('retryTransientErrors', () => {
await expect(retryTransientEsErrors(esCallMock)).rejects.toThrow(error);
expect(esCallMock).toHaveBeenCalledTimes(1);
});

it('retries with additionalResponseStatuses', async () => {
const error = new EsErrors.ResponseError({ statusCode: 123, meta: {} as any, warnings: [] });
const esCallMock = jest.fn().mockRejectedValueOnce(error).mockResolvedValue('success');
expect(await retryTransientEsErrors(esCallMock, { additionalResponseStatuses: [123] })).toEqual(
'success'
);
expect(esCallMock).toHaveBeenCalledTimes(2);
});
});
13 changes: 9 additions & 4 deletions x-pack/plugins/fleet/server/services/epm/elasticsearch/retry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,29 @@ const retryResponseStatuses = [
410, // Gone
];

const isRetryableError = (e: any) =>
const isRetryableError = (e: any, additionalResponseStatuses: number[] = []) =>
e instanceof EsErrors.NoLivingConnectionsError ||
e instanceof EsErrors.ConnectionError ||
e instanceof EsErrors.TimeoutError ||
(e instanceof EsErrors.ResponseError && retryResponseStatuses.includes(e?.statusCode!));
(e instanceof EsErrors.ResponseError &&
[...retryResponseStatuses, ...additionalResponseStatuses].includes(e?.statusCode!));

/**
* Retries any transient network or configuration issues encountered from Elasticsearch with an exponential backoff.
* Should only be used to wrap operations that are idempotent and can be safely executed more than once.
*/
export const retryTransientEsErrors = async <T>(
esCall: () => Promise<T>,
{ logger, attempt = 0 }: { logger?: Logger; attempt?: number } = {}
{
logger,
attempt = 0,
additionalResponseStatuses = [],
}: { logger?: Logger; attempt?: number; additionalResponseStatuses?: number[] } = {}
): Promise<T> => {
try {
return await esCall();
} catch (e) {
if (attempt < MAX_ATTEMPTS && isRetryableError(e)) {
if (attempt < MAX_ATTEMPTS && isRetryableError(e, additionalResponseStatuses)) {
const retryCount = attempt + 1;
const retryDelaySec = Math.min(Math.pow(2, retryCount), 64); // 2s, 4s, 8s, 16s, 32s, 64s, 64s, 64s ...

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,9 +703,13 @@ async function handleTransformInstall({
// start transform by default if not set in yml file
// else, respect the setting
if (startTransform === undefined || startTransform === true) {
await esClient.transform.startTransform(
{ transform_id: transform.installationName },
{ ignore: [409] }
await retryTransientEsErrors(
() =>
esClient.transform.startTransform(
{ transform_id: transform.installationName },
{ ignore: [409] }
),
{ logger, additionalResponseStatuses: [400] }
);
logger.debug(`Started transform: ${transform.installationName}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ import {
export default function (providerContext: FtrProviderContext) {
const { loadTestFile, getService } = providerContext;

// FLAKY: https://github.com/elastic/kibana/issues/72874
describe.skip('endpoint', function () {
describe('endpoint', function () {
const ingestManager = getService('ingestManager');
const log = getService('log');
const endpointTestResources = getService('endpointTestResources');
Expand Down

0 comments on commit 7449b0a

Please sign in to comment.