Skip to content

Commit

Permalink
Add support for decorating 429 errors in the saved objects client
Browse files Browse the repository at this point in the history
  • Loading branch information
mikecote committed Aug 21, 2020
1 parent 7376e4c commit cae4933
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ describe('savedObjectsClient/decorateEsError', () => {
expect(SavedObjectsErrorHelpers.isConflictError(error)).toBe(true);
});

it('makes TooManyRequests a SavedObjectsClient/tooManyRequests error', () => {
const error = new esErrors.ResponseError(
elasticsearchClientMock.createApiResponse({ statusCode: 429 })
);
expect(SavedObjectsErrorHelpers.isTooManyRequestsError(error)).toBe(false);
expect(decorateEsError(error)).toBe(error);
expect(SavedObjectsErrorHelpers.isTooManyRequestsError(error)).toBe(true);
});

it('makes NotAuthorized a SavedObjectsClient/NotAuthorized error', () => {
const error = new esErrors.ResponseError(
elasticsearchClientMock.createApiResponse({ statusCode: 401 })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const responseErrors = {
isRequestEntityTooLarge: (statusCode: number) => statusCode === 413,
isNotFound: (statusCode: number) => statusCode === 404,
isBadRequest: (statusCode: number) => statusCode === 400,
isTooManyRequests: (statusCode: number) => statusCode === 429,
};
const { ConnectionError, NoLivingConnectionsError, TimeoutError } = esErrors;
const SCRIPT_CONTEXT_DISABLED_REGEX = /(?:cannot execute scripts using \[)([a-z]*)(?:\] context)/;
Expand Down Expand Up @@ -76,6 +77,10 @@ export function decorateEsError(error: EsErrors) {
return SavedObjectsErrorHelpers.createGenericNotFoundError();
}

if (responseErrors.isTooManyRequests(error.statusCode)) {
return SavedObjectsErrorHelpers.decorateTooManyRequestsError(error, reason);
}

if (responseErrors.isBadRequest(error.statusCode)) {
if (
SCRIPT_CONTEXT_DISABLED_REGEX.test(reason || '') ||
Expand Down
47 changes: 47 additions & 0 deletions src/core/server/saved_objects/service/lib/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,53 @@ describe('savedObjectsClient/errorTypes', () => {
});
});

describe('TooManyRequests error', () => {
describe('decorateTooManyRequestsError', () => {
it('returns original object', () => {
const error = new Error();
expect(SavedObjectsErrorHelpers.decorateTooManyRequestsError(error)).toBe(error);
});

it('makes the error identifiable as a TooManyRequests error', () => {
const error = new Error();
expect(SavedObjectsErrorHelpers.isTooManyRequestsError(error)).toBe(false);
SavedObjectsErrorHelpers.decorateTooManyRequestsError(error);
expect(SavedObjectsErrorHelpers.isTooManyRequestsError(error)).toBe(true);
});

it('adds boom properties', () => {
const error = SavedObjectsErrorHelpers.decorateTooManyRequestsError(new Error());
expect(error).toHaveProperty('isBoom', true);
});

describe('error.output', () => {
it('defaults to message of error', () => {
const error = SavedObjectsErrorHelpers.decorateTooManyRequestsError(new Error('foobar'));
expect(error.output.payload).toHaveProperty('message', 'foobar');
});

it('prefixes message with passed reason', () => {
const error = SavedObjectsErrorHelpers.decorateTooManyRequestsError(
new Error('foobar'),
'biz'
);
expect(error.output.payload).toHaveProperty('message', 'biz: foobar');
});

it('sets statusCode to 429', () => {
const error = SavedObjectsErrorHelpers.decorateTooManyRequestsError(new Error('foo'));
expect(error.output).toHaveProperty('statusCode', 429);
});

it('preserves boom properties of input', () => {
const error = Boom.tooManyRequests();
SavedObjectsErrorHelpers.decorateTooManyRequestsError(error);
expect(error.output).toHaveProperty('statusCode', 429);
});
});
});
});

describe('EsCannotExecuteScript error', () => {
describe('decorateEsCannotExecuteScriptError', () => {
it('returns original object', () => {
Expand Down
14 changes: 14 additions & 0 deletions src/core/server/saved_objects/service/lib/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ const CODE_REQUEST_ENTITY_TOO_LARGE = 'SavedObjectsClient/requestEntityTooLarge'
const CODE_NOT_FOUND = 'SavedObjectsClient/notFound';
// 409 - Conflict
const CODE_CONFLICT = 'SavedObjectsClient/conflict';
// 429 - Too Many Requests
const CODE_TOO_MANY_REQUESTS = 'SavedObjectsClient/tooManyRequests';
// 400 - Es Cannot Execute Script
const CODE_ES_CANNOT_EXECUTE_SCRIPT = 'SavedObjectsClient/esCannotExecuteScript';
// 503 - Es Unavailable
Expand Down Expand Up @@ -162,6 +164,18 @@ export class SavedObjectsErrorHelpers {
return isSavedObjectsClientError(error) && error[code] === CODE_CONFLICT;
}

public static decorateTooManyRequestsError(error: Error, reason?: string) {
return decorate(error, CODE_TOO_MANY_REQUESTS, 429, reason);
}

public static createTooManyRequestsError(type: string, id: string) {
return SavedObjectsErrorHelpers.decorateTooManyRequestsError(Boom.tooManyRequests());
}

public static isTooManyRequestsError(error: Error | DecoratedError) {
return isSavedObjectsClientError(error) && error[code] === CODE_TOO_MANY_REQUESTS;
}

public static decorateEsCannotExecuteScriptError(error: Error, reason?: string) {
return decorate(error, CODE_ES_CANNOT_EXECUTE_SCRIPT, 400, reason);
}
Expand Down

0 comments on commit cae4933

Please sign in to comment.